I have two functions which call external library functions except one has two extra parameters (let’s say the extra parameters are always zero).
void func1(int a, int b)
{
libDoAThing(a, b);
}
void func1Special(int a, int b)
{
libDoAThingWithTwoExtraParams(a, b, 0, 0);
}
Is there any way to combine these methods into a single method which can be called as such:
func1<libDoAThing>{10, 10};
func1<libDoAThingWithTwoExtraParams>{10, 10};
I'm not sure how to handle the two extra parameters in the function call when templating.
If you can use at least C++11, you can fix the last two parameters with std::bind() or, I suggest, with a lambda function.
So you don't need a template parameter: you can pass the resulting lambda as an argument of func1() and call it inside.
The following is a full working example with lambda
#include <iostream>
void foo (int a, int b)
{ std::cout << "foo: " << a << ", " << b << std::endl; }
void bar (int a, int b, int c, int d)
{ std::cout << "bar: " << a << ", " << b << ", " << c << ", "
<< d << std::endl; }
void func1 (void(*f)(int, int), int x, int y)
{ f(x, y); }
int main ()
{
auto l { [](int a, int b){ bar(a, b, 0, 0); } };
func1(foo, 1, 2);
func1(l, 3, 4);
}
Related
I want a function that can accept any type of argument and then in the implementation, can check if the type is integer and then can throw a message. For example the function can be called like the following,
add(10, 12);
Output : "correct input. addition is 22"
add(10, "hello")
Output : "wrong input"
add(10)
Output : "wrong input! missing arguments"
Is it possible to achieve this in C++?
Using overloading I will have to create functions of all possible combination such as (int, double), (double, int), (int, string), (string, int) and so on, so is there any other way?
Since C++17, you can use std::any and std::any_cast:
#include <any>
#include <iostream>
void add(const std::any& a = "", const std::any& b = "")
{
try {
const int ia = std::any_cast<int>(a);
const int ib = std::any_cast<int>(b);
std::cout << "correct input. addition is " << ia + ib << std::endl;
}
catch (...) {
std::cout << "wrong input" << std::endl;
}
}
int main()
{
add(10, "hello");
add(10, 12);
add(10);
add();
}
Demo
A pre-C++17 solution:
#include <iostream>
void add(int a, int b)
{
std::cout << "correct input. addition is " << a + b << std::endl;
}
template<typename... Ts>
void add(Ts...)
{
std::cout << "wrong input" << std::endl;
}
int main()
{
add(10, "hello");
add(10, 12);
add(10);
add();
}
Demo
The first thing to do is write an overload that accepts exactly 2 ints:
void add(int a, int b) {
std::cout << "Correct input. Answer is " << a + b << "\n";
}
And that should generally be enough. If a call is made with an incorrect number of arguments, or with 2 arguments that can't be converted to int, the compiler will produce an error for you.
If you don't want an error, but instead want to print an error message at runtime, you can just add overloads. As you've noticed, adding overloads for explicit types isn't really going to work, but you can add a generic function (a function template) that will accept anything:
void add(auto ...) {
std::cout << "Incorrect input\n";
}
Note that pre-C++20, the signature has to be spelled
template<typename ...Ts>
void add(Ts ...);
You can continue adding more overloads if you want more specific error messages, e.g. for a call where only one argument is passed:
void add(auto) {
std::cout << "Insufficient arguments\n";
}
Here's a demo.
When we start learing about "Function Overloading" then we are given with the example of functions of same name but with either different number of parameters or different datatypes of parameters like:
void add(int a, int b) //function 1
{
cout << "sum = " << (a + b);
}
void add(double a, double b) //funciton 2
{
cout << endl << "sum = " << (a + b);
}
int main()
{
add(10, 2);
add(5.3, 6.2);
return 0;
}
In this both the overloaded add functions are delared globally and they have same scope(global) also.
Now, my question is that if I define two functions with same name inside different blocks(one as global and other one inside a class) then will it still be called as "Function Overloading"?
Like:
void display() //function 1
{
cout<<"global diaplay() function";
}
class example
{
public:
void display(char a) //funciton 2
{
cout<<"display() function inside a class called by passing argument:"<<a;
}
};
int main()
{
display();
example M;
M.display('o');
return 0;
}
Explaination with an example will be very helpful.
In one of my projects I'm using a small utility function, which takes a Message struct and a lambda function, that modifies this message struct.
Now, I unintentionally passed a lambda without the necessary reference &. It perfectly compiles, but doesn't gave the desired output.
As for me, there should be one of the two following behaviors:
Forgetting to write auto&, but just auto should lead to compilation errors
Writing just auto should be interpreted as auto&.
It is possible to prevent compilation in case of a missing & or even better to interpret auto as auto& automatically?
#include <iostream>
#include <functional>
#include <boost/variant.hpp>
struct Message {
int x;
int y;
};
void changeMessage(Message& m, const std::function<void(Message&)>& messageModifier) {
std::cout << "Message before:" << m.x << " " << m.y << "\n";
messageModifier(m);
std::cout << "Message after:" << m.x << " " << m.y << "\n";
}
int main(int, char**) {
{
std::function<void(int&)> f = [](int&) {};
std::function<void(int)> g = [](int) {};
f = g; // This compiles.
}
{
std::function<void(int&)> f = [](int&) {};
std::function<void(int)> g = [](int) {};
//g = f; // This does not compile. Makes perfect sense.
}
Message m{ 10,20 };
{
changeMessage(m, [](auto m) { m.x++; m.y--; }); // User unintentionally forgot &! Can I prevent this from compilation?
std::cout << "Message outside: " << m.x << " " << m.y << "\n";
}
{
changeMessage(m, [](auto& m) { m.x++; m.y--; });
std::cout << "Message outside: " << m.x << " " << m.y << "\n";
}
}
One way to prevent passing Message by value (and auto itself is never a reference) is to disable copy construction:
struct Message {
Message() = default;
Message(const Message&) = delete;
int x;
int y;
};
Another solution suggested by #L. F. is to check that lambda doesn't accept rvalues:
template<class Fn>
void change_message(Message& m, Fn fn) {
static_assert(!std::is_invocable_v<Fn, Message&&>);
fn(m);
}
I want to implement a function like this
double d = string_to("1223.23",double);
int i = string_to("1223",int);
bool d = string_to("1",bool);
How can I pass the bool, int, double data type to implement this in c++?
Types line int, double and bool can only be passed as template parameters.
You can use templates like this:
#include <string>
#include <sstream>
#include <iostream>
template<typename DataType>
DataType string_to(const std::string& s)
{
DataType d;
std::istringstream(s) >> d; // convert string to DataType
return d;
}
int main()
{
double d = string_to<double>("1223.23");
int i = string_to<int>("1223");
bool b = string_to<bool>("1");
std::cout << "d: " << d << '\n';
std::cout << "i: " << i << '\n';
std::cout << "b: " << b << '\n';
}
As an alternative you can pass your numeric types by reference and rely on function overloading to select the correct function:
void string_to(const std::string& s, double& d)
{
d = std::stod(s);
}
void string_to(const std::string& s, int& i)
{
i = std::stoi(s);
}
void string_to(const std::string& s, bool& b)
{
std::istringstream(s) >> std::boolalpha >> b;
}
int main()
{
double d;
int i;
bool b;
string_to("1223.23", d);
string_to("1223", i);
string_to("true", b);
std::cout << "d: " << d << '\n';
std::cout << "i: " << i << '\n';
std::cout << "b: " << b << '\n';
}
Also you could templatize the second method (an exercise for the reader).
If you really want to do this, you can pass the type by using the typeid operator.
E.g. double d = string_to("1223.23", typeid(double));
Using the library functions atoi, stod would make more sense.
If you're aiming to write more uniform code then you could write a Converter object and use method overloading to get automatic selection by type.
class Converter
{
public:
void fromString(double& value, const char* string);
void fromString(int& value, const char* string);
void fromString(long& value, const char* string);
};
Here's another way that uses tag dispatching. You can compile and run this example.
#include <iostream>
#include <string>
#include <cmath>
namespace detail {
// declare the concept of conversion from a string to something
template<class To>
To string_to(const std::string&);
// make some models of the concept
template<>
int string_to<int>(const std::string& s) {
return atoi(s.c_str());
}
template<>
double string_to<double>(const std::string& s) {
return atof(s.c_str());
}
template<>
std::string string_to<std::string>(const std::string& s) {
return s;
}
// ... add more models here
}
// define the general case of conversion from string with a model tag
// note the unused parameter allows provision of a model that is never used
// thus the model will in all likelihood be optimised away
template<class To>
To string_to(const std::string& from, const To& /* model_tag is unused */)
{
// dispatch to correct conversion function using the To type
// as a dispatch tag type
return detail::string_to<To>(from);
}
using namespace std;
int main()
{
// examples
int a = string_to("100", a);
double b = string_to("99.9", b);
const string s = string_to("Hello", s);
cout << s << " " << a << " " << b << endl;
return 0;
}
output:
Hello 100 99.9
I'm new to C++ and could not figure out how can I define a variable that holds 3 values,
e.g. coordinates hold 2 values, as (x,y).
I tried:
typedef int U_K(int a,int b,int c);
but that doesn't seem to work.
I'd really appreciate a quick simple answer :)
Thanks!
edit:
So i did this :
struct U_K{
float a,b,c;
};
U_K Uk; //this line
is this wrong? because i get "unknown type name U_K" for that line... i first though its because i needed to declare it under the function i am going to use the struct for, but turns out there is the error for both cases.
the shortest way is to use a struct
struct U_K
{
int a,b,c;
};
usage:
U_K tmp;
tmp.a = 0;
tmp.b = 1;
tmp.c = 2;
You can add complexity to that type by adding member function/constructors to make the usage of U_K easier:
struct U_K
{
int a,b,c;
U_K() //default constructor
:a(0)
,b(0)
,c(0)
{}
U_K(int _a_value,int _b_value, int _c_value) //constructor with custom values
:a(_a_value)
,b(_b_value)
,c(_c_value)
{}
};
//usage:
int main()
{
U_K tmp(0,1,2);
std::cout << "a = " << tmp.a << std::endl;//print a
std::cout << "b = " << tmp.b << std::endl;//print b
std::cout << "c = " << tmp.c << std::endl;//print c
}
Alternatively you can use std::tuple to obtain the same result. Using it is different:
std::tuple<int,int,int> t = std::make_tuple(0,1,2);
std::cout << "a = " << std::get<0>(t) << std::endl;//print first member
std::cout << "b = " << std::get<1>(t) << std::endl;//print second member
std::cout << "c = " << std::get<2>(t) << std::endl;//print third member
If you are learning c++ now you should know that the implementation std::tuple is much more complex than a trivial struct and to understand it you need to learn about templates and variadic templates.
struct TypeWith3Ints
{
public:
int a;
int b;
int c;
};
Use std::array<int, 3> which is to be preferred over tuple in this case as a homogenous container can be used.
If you want to typedef:
#include <array>
typedef std::array<int, 3> X;
Use std::tuple, then you don't have to make your own structure. Just write
std::tuple<int, int, int> your_tuple(a,b,c);
std::cout << std::get<1>(your_tuple) << ' '; // b
your_tuple = std::make_tuple(c,d,e);
std::cout << std::get<0>(your_tuple) << ' '; // c
If you want your own name, use alias, like:
typedef std::tuple<int, int, int> your_name;
your_name your_object(a,b,c); //your_tuple
std::cout << std::get<2>(your_tuple) << ' '; // c
If you want, your own structure, and if you want to write object(x,y,z), than you should make constructor or even overload operator (). It's more complicated. I suggest not to do it. Unless that has a deeper meaning. If you really want it, it could look like:
struct coordinate
{
int x,y,z;
coordinate(int a, int b, int c) : x(a), y(b), z(c)
{}
void operator()(int a, int b, int c)
{
x = a;
y = b;
z = c;
}
} my_object(10,20,30);
int main()
{
std::cout<<my_object.x<<' '<<my_object.y<<' '<<my_object.z<<'\n';
my_object(30,40,50);
std::cout<<my_object.x<<' '<<my_object.y<<' '<<my_object.z<<'\n';
return 0;
}
You can also do not make constructor and use {} notation.