Passing functions with different number of parameters as argument in C++ - c++

[Edited] Based on the feedback from comments, I have rephrased my question.
In C++, is it possible to create a function func that receives another function f as a parameter, if the number of arguments of f might change?
According to this thread, a syntax in C like
void func ( void (*f)(int) );
would help if I already know the number of arguments f receives, but that's not my case.
I want to use func with different functions f1, f2, etc., each of them may or may not have the same number of parameters. For example, f1 could take only one argument, but f2 could take two. That's why I'm trying to look for a way to pass f without specifying the number of arguments. Thanks!

The Q&A you link is for C. In C++ you can pass a function pointer but not always this is the best alternative.
Your question leaves out the crucial part: How do you plan to call f in func when you don't know the number of parameters?
You can do type erasure and remove information of a type easily (eg number of arguments of a function), but latest when you call the function you need to know again how many parameters to pass.
As it isn't perfectly clear what you want to do with the fs that take different number of parameters I will interpret your question like this: Instead of passing functions of different arity to func you can pass a functor with overloaded operator(). Then you can call it with different number of parameters:
#include <iostream>
#include <string>
template <typename F>
void func(F f, int num_params){
if (num_params == 1){
f("Hello");
} else if (num_params == 2) {
f("Hello","World");
}
}
struct functor {
void operator()(const std::string& s){ std::cout << s << "\n";}
void operator()(const std::string& s1,const std::string& s2) { std::cout << s1 << " " << s2 << "\n";}
};
int main() {
func(functor{},1);
func(functor{},2);
}
However, my func is only valid for a functor type that has both, an operator() that can be called with one string literal, and an operator() that can be called with two string literals.

Related

Name the type of a template function in C++ [duplicate]

It is necessary for me to use std::function but I don't know what the following syntax means.
std::function<void()> f_name = []() { FNAME(); };
What is the goal of using std::function? Is it to make a pointer to a function?
std::function is a type erasure object. That means it erases the details of how some operations happen, and provides a uniform run time interface to them. For std::function, the primary1 operations are copy/move, destruction, and 'invocation' with operator() -- the 'function like call operator'.
In less abstruse English, it means that std::function can contain almost any object that acts like a function pointer in how you call it.
The signature it supports goes inside the angle brackets: std::function<void()> takes zero arguments and returns nothing. std::function< double( int, int ) > takes two int arguments and returns double. In general, std::function supports storing any function-like object whose arguments can be converted-from its argument list, and whose return value can be converted-to its return value.
It is important to know that std::function and lambdas are different, if compatible, beasts.
The next part of the line is a lambda. This is new syntax in C++11 to add the ability to write simple function-like objects -- objects that can be invoked with (). Such objects can be type erased and stored in a std::function at the cost of some run time overhead.
[](){ code } in particular is a really simple lambda. It corresponds to this:
struct some_anonymous_type {
some_anonymous_type() {}
void operator()const{
code
}
};
an instance of the above simple pseudo-function type. An actual class like the above is "invented" by the compiler, with an implementation defined unique name (often including symbols that no user-defined type can contain) (I do not know if it is possible that you can follow the standard without inventing such a class, but every compiler I know of actually creates the class).
The full lambda syntax looks like:
[ capture_list ]( argument_list )
-> return_type optional_mutable
{
code
}
But many parts can be omitted or left empty. The capture_list corresponds to both the constructor of the resulting anonymous type and its member variables, the argument_list the arguments of the operator(), and the return type the return type. The constructor of the lambda instance is also magically called when the instance is created with the capture_list.
[ capture_list ]( argument_list ) -> return_type { code }
basically becomes
struct some_anonymous_type {
// capture_list turned into member variables
some_anonymous_type( /* capture_list turned into arguments */ ):
/* member variables initialized */
{}
return_type operator()( argument_list ) const {
code
}
};
Note that in c++20 template arguments were added to lambdas, and that isn't covered above.
[]<typename T>( std::vector<T> const& v ) { return v.size(); }
1 In addition, RTTI is stored (typeid), and the cast-back-to-original-type operation is included.
Let's break the line apart:
std::function
This is a declaration for a function taking no parameters, and returning no value. If the function returned an int, it would look like this:
std::function<int()>
Likewise, if it took an int parameter as well:
std::function<int(int)>
I suspect your main confusion is the next part.
[]() { FNAME(); };
The [] part is called a capture clause. Here you put variables that are local to the declaration of your lambda, and that you want to be available within the lambda function itself. This is saying "I don't want anything to be captured". If this was within a class definition and you wanted the class to be available to the lambda, you might do:
[this]() { FNAME(); };
The next part, is the parameters being passed to the lambda, exactly the same as if it was a regular function. As mentioned earlier, std::function<void()> is a signature pointing to a method that takes no parameters, so this is empty also.
The rest of it is the body of the lambda itself, as if it was a regular function, which we can see just calls the function FNAME.
Another Example
Let's say you had the following signature, that is for something that can sum two numbers.
std::function<int(int, int)> sumFunc;
We could now declare a lambda thusly:
sumFunc = [](int a, int b) { return a + b; };
Not sure if you're using MSVC, but here's a link anyway to the lamda expression syntax:
http://msdn.microsoft.com/en-us/library/dd293603.aspx
Lambdas with captures (stateful lambdas) cannot be assigned to each other since they have unique types, even if they look exactly the same.
To be able to store and pass around lambdas with captures, we can use "std::function" to hold a function object constructed by a lambda expression.
Basically "std::function" is, to be able to assign lambda functions with different content structures to a lambda function object.
Exp :
auto func = [](int a){
cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //ATTENTION(ERROR!): assigning a new structure to the same object
cout << "x:" << x << ",a:" << a << endl;
};
func(2);
So the above usage will be incorrect.
But if we define a function object with "std::function":
auto func = std::function<void(int)>{};
func = [](int a){
cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //CORRECT. because of std::function
//...
};
int y = 11;
func = [x,y](int a){ //CORRECT
//...
};

execution order of functors in std::bind() parameter list (maybe not related to evaluation order of function parameter)

I was just wondering and write the following code: (I am not asking for work arounds, I just want to know whether bind() handles this perfectly or not). Besides, I think bind can handle this and define an order for it, but I am not sure or maybe it is just a parameter evaluation order issue.
#include <functional>
#include <utility>
#include <iostream>
using namespace std;
class increment{
public :
string operator()(int& x)
{
++x;
return string {"dumb_return_value"};
}
};
class multiply{
public :
string operator()(int& x)
{
x = x * 2;
return string {"dumb_return_value"};
}
};
template <typename A, typename B>
class do_nothing{
public :
void operator()(A , B)
{
return;
}
};
int main()
{
int x = 0;
increment increment_object;
multiply multiply_object;
do_nothing<string,string> do_nothing_object;
bind(do_nothing_object,bind(increment_object,ref(x)),bind(multiply_object,ref(x)))();
cout << x << endl;//output 2
x = 0;
bind(do_nothing_object,bind(multiply_object,ref(x)),bind(increment_object,ref(x)))();
cout << x << endl;//output 1
}
compilation option : std=c++1z
So, I use the reference semantics to amplify the difference here. What is the execution order of these sub-functions increment and multiply? Does bind handle this providently and define an order, or it is dependent on function parameter evaluation sequence, which is compiler-specific? If std::bind() handles this providently, please cite it, thanks!
PS: one reason why I ask this question is here: c++ equivalent of java's andThen function to composite new function?
Using this draft as reference.
func.bind.bind [20.10.9.1.3] doesn't specify when the bind sub-expressions are evaluated or their order.
It simply states that if one of the arguments to bind is a bind-expression result, the return value of the outer bind expression uses the result of calling the inner bind-expression with the arguments passed to the outer bind expression. It gives no sequencing information for when those values are evaluated; one may presume that it "must" happen after the outer bind expression is passed arguments, but that (as far as I can tell) only something I can conclude with common sense, not from the standard text itself.

Lambda as template function

I have a very strange problem. To keep things simple, lets say I want to have a function which takes 2 functions with the same declaration as arguments
template<typename Func>
void foo(Func a, Func b)
{
std::cout << "good";
}
To try things out I took putchar from cstdio, and created an identical function to match the putchar.
int myPutcharFunc(int)
{
return 0;
}
int main()
{
auto myPutcharLambda = [](int) -> int
{
return 0;
};
foo(putchar, myPutcharFunc); // okay
foo(putchar, myPutcharLambda); //deduced conflicting types for parameter 'Func' ('int (__attribute__((__cdecl__)) *)(int)' and 'main()::<lambda(int)>')
}
Now, the lambda does not want to compile (the key is I want to use lambda capture).
So lets add template specialization, because the programmer is wiser than the machine, right? :)
template<typename Func>
void foo(Func a, Func b)
{
std::cout << "good";
}
template<>
void foo(int(*)(int), int(*)(int))
{
std::cout << "good";
}
No luck, the same error - why?
But for some reason, when I comment out the template specialization:
//template<>
void foo(int(*)(int), int(*)(int))
{
std::cout << "good";
}
The code compiles. I obviously do not want to overload foo for EVERY set of function's arguments - thats what templates are for. Every step was tested both with msvc++ and g++. What am I doing wrong?
Two possibilities.
1: Just put + in front of the lambda:
foo(putchar, +myPutcharLambda);
That works because unary + expects an integer-like value, such as a pointer. Therefore, the lambda converts to a function pointer.
Ultimately a (non-capturing) lambda doesn't have the same type as a function pointer, even though it's willing to convert to a function pointer.
How is a compiler supposed to know which conversions are allowed to make two objects of the same type?
2: There is another option, making use of the fact that the ?: is willing to do some conversions, converting one type to another in some circumstances.
template<typename Func1, typename Func2>
void foo2(Func1 a, Func2 b)
{
using common_type = decltype(true?a:b); // or 'false', it doesn't matter
foo<common_type>(a,b);
}
Every lambda is a different type, so you'll need to have two different template parameters to get them
template<typename FuncA, typename FuncB>
void foo(FuncA a, FuncB b)
Types don't decay when deducing template types (SEE COMMENT FOR CORRECTION). So a lambda remains a lambda and doesn't decay to a function pointer. Same reason a string literal is deduced as a char[N] instead of a const char *.
With your second example using specialization, it doesn't want to use your specialization, since the lambda is not a function pointer. You can cast the Lambda to a function pointer and make it work: https://godbolt.org/g/ISgPci The trick you can do here is say +my_lambda because + is defined for pointers so it will force the non-capturing lambda to become a function pointer.
A lambda has its own type which can decay to a function pointer but not in the case of a template function match, it will for the real function as you found because of the implicit conversion.
In the case of matching to a template you need to disambiguate and explicitly instantiate foo with the type you want or convert the lambda to a function pointer.
foo<decltype(putchar)>(putchar, myPutcharLambda);
or
foo(putchar, +myPutcharLambda);

In C++, is it possible to pass in two different data types to a template function?

I'm trying to calculate the absolute value of two numeric values passed in by a user, but allowing the user to enter multiple data types (i.e. an integer and a double, or a char and a float). My initial thought is to use a function sort of like this:
template <class T1, class T2>
void findAbs(const T1& var1, const T2& var2)
{
cout<<"Enter two numbers: "<<endl;
cin>>var1>>var2;
cout<<abs(var1)<<" "<<abs(var2)<<endl;
}
If this is the correct way to do it though, I have no idea how I'd call it in the main function since it seems I'd have to declare the parameters as one data type or another. Any help would be much appreciated!
First off, your example won't compile, because you're taking the parameters by const-reference, and then trying to read into them from the stream. You should take them by non-const reference instead.
With this fixed, you could simply use the function like this:
int main()
{
int i;
float f;
double d;
char c;
findAbs(i, f);
findAbs(c, d);
findAbs(d, i);
//etc.
}
Of course, the type of the arguments must be known in each call site. Templates are a purely compile-time construct. If you were hoping to somehow use the template to differentiate between the end-user typing c, 42 or -3.14, you can't, as that's run-time information.
I have no idea how I'd call it in the main function since it seems I'd have to declare the parameters as one data type or another.
No, template parameters can be deduced in this case. But the main problem is that operator>> of std::cin modifies the parameters, therefore you shouldn't declare them const:
template <class T1, class T2>
void findAbs(T1& var1, T2& var2) {
std::cout << "Enter two numbers: " << std::endl;
std::cin >> var1 >> var2;
std::cout << std::abs(var1) << ' ' << std::abs(var2) << std::endl;
}
Then you should be able to call:
int x, y;
findAbs(x, y);
It might be wise to consider using a single template parameter for both of the arguments though.
Yes, but it depends on whether or not the types you pass in would lead to a piece of code which is valid. Expand the template in your head (or type it out, whatever). Does calling abs on variables of type T1 and T2 make sense? Would it compile? How about the calls to cin? If so, then yes, your code will work.

Variable arguments

Is there a non-boost way to create a function with variable arguments? I know the argument types number of arguments and they are usually less then 5, all of the same type.
I need to know if there is a way without supplying the argument count or ending the param list with null.
I know the argument types and they are usually less then 5.
If it is not going to be greater than 5, then simple overloads may do the work. Call the overload which accepts maximam number of arguments from all other overloads accepting less than 5 arguments, or define a worker (internal) function, call this from the overloads.
If possible, you could use default values for some of the parameters, if that helps reducing the number of overloaded functions.
In C++11, you could use variadic-template.
For up to 5 arguments all of the same type, simple overloads can do the trick.
For more generality, supporting any number of arguments of the same type, just pass a collection such as a std::vector.
For a C++03 technique to build such a collection on the fly in each call, see my other answer; for C++11, if you do not need to support Visual C++ you can use curly braces initializer lists as actual arguments.
Is cstdarg what you are looking for? This is the standard C++ way to generate functions with variable numbers of arguments.
You should be able achieve passing variable arguments using va_list.
You can:
if you're using C++11 you can use variadic templates, otherwise...
provide overloads
use arguments which default to some sentinel values you can recognise ala f(const T& v1 = missing, const T& v2 = missing, ...) { if (v5 != missing) ...
create a simple helper template that can optionally be constructed from the data type and has a bool to track whether it was
you may need to support types without default constructors by either using new/delete (simple and safe but slow) or having an aligned buffer you placement new into, manually destroy etc. (fiddly and easier to get wrong but faster)
some compilers have variadic macro support
if you're prepared to change the calling syntax a bit, you can use any number of things:
accept a vector (using a union or variant if the types differ)
accept an array (possibly using the template <size_t N> void f(T (&data)[N]) { ... } trick to have the compiler provide the array size to you automatically)
some kind of lhs object to which extra values can be supplied using an operator such as operator, or operator<<
As a general C++03 solution you can provide a setter that returns a reference to the object that it's called on, so that it can be called again. And again. And so on, called chaining.
It's the same scheme as iostreams use for operator<<.
E.g.
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
void foo( char const s[] )
{
cout << s << endl;
}
class StringBuilder
{
private:
string s_;
template< class Type >
string fastStringFrom( Type const& v )
{
stringstream stream;
stream << v;
return stream.str();
}
char const* fastStringFrom( char const* s )
{
return s;
}
string const& fastStringFrom( string const& s )
{
return s;
}
public:
template< class Type >
StringBuilder& operator<<( Type const& v )
{
s_ += fastStringFrom( v );
return *this; // Supports chaining.
}
operator string const& () const { return s_; }
operator char const* () const { return s_.c_str(); }
};
int main()
{
typedef StringBuilder S;
foo( S() << "6*7 = " << 6*7 << "." ); // Any number of arguments.
}
Instead of converting the argument values to text, you just do whatever it is that you need. For example, with a fixed set of possible types you can store the arguments in a collection.
If you do not need to support the Visual C++ compiler, then alternatively you can use a C++11 variadic template.