I have the below code, where a class is trying to take one of two std::function signatures through its constructor. I'm able to get the signature that has the double parameter to compile, but the parameter-less signature fails to compile, saying the call is ambiguous.
#include <functional>
class Foo
{
public:
void baz(double value) {
}
};
class Bar
{
public:
void baz() {
}
};
class Overloader {
public:
Overloader(std::function<void(double)> inFuncWithArg)
: funcWithArg(inFuncWithArg)
{
}
Overloader(std::function<void(void)> inFuncNoArg)
: funcNoArg(inFuncNoArg)
{
}
private:
std::function<void(double)> funcWithArg;
std::function<void(void)> funcNoArg;
};
int main()
{
Foo foo;
Bar bar;
// Compiles
Overloader overloader1(std::bind(static_cast<void(Foo::*)(double)>(&Foo::baz)
, &foo, std::placeholders::_1));
// Fails to compile - "call of overloaded ‘Overloader(std::_Bind_helper::type)’ is ambiguous"
Overloader overloader2(std::bind(static_cast<void(Bar::*)(void)>(&Bar::baz)
, &bar));
return 0;
}
What am I missing that's causing this to fail? Also, are there any less-verbose ways to do this?
Here's the full error output
main.cpp: In function ‘int main()’:
main.cpp:51:20: error: call of overloaded ‘Overloader(std::_Bind_helper::type)’ is ambiguous
, &bar));
^
main.cpp:32:5: note: candidate: Overloader::Overloader(std::function)
Overloader(std::function<void(void)> inFuncNoArg)
^~~~~~~~~~
main.cpp:27:5: note: candidate: Overloader::Overloader(std::function)
Overloader(std::function<void(double)> inFuncWithArg)
^~~~~~~~~~
This question is more about std::bind than std::function.
The result of the expression
std::bind(&Foo::baz, &foo, std::placeholders::_1)
is invocable with one or more arguments, where the first argument is convertible to double.
The result of the expression
std::bind(&Bar::baz, &bar)
is invocable with zero or more arguments, with no restrictions.
The first expression can thus only initialize std::function<void(double)>, but the second expression can initialize either std::function<void(double)> or std::function<void(void)> and is ambiguous.
Genuinely, do not use std::bind. You can use std::bind_front if you have it. Alternatively, use a lambda.
std::bind_front:
std::bind_front(&Foo::baz, &foo)
std::bind_front(&Bar::baz, &bar)
lambda:
[&foo](double) { foo.baz(value); }
[&bar] { bar.baz(); }
Just use a lambda:
auto overloader1 = [&foo](double value) { foo.baz(value); };
auto overloader2 = [&bar]() { bar.baz(); }
Related
I'd like to create a class where the client can store a lambda expression like []() -> void {} as a field of the class, but I can't figure out how to do so. One answer suggested using decltype, which I tried with no success. Here is a ideone source link. The below is the source and result:
#include <cstdio>
auto voidLambda = []()->void{};
class MyClass {
public:
decltype(voidLambda) t;
MyClass(decltype(voidLambda) t) {
this->t = t;
}
};
int main() {
MyClass([] {
printf("hi");
});
}
Result:
prog.cpp: In constructor 'MyClass::MyClass(<lambda()>)':
prog.cpp:3:79: error: no matching function for call to '<lambda()>::__lambda0()'
prog.cpp:2:20: note: candidates are: <lambda()>::<lambda>(const<lambda()>&)
prog.cpp:2:20: note: <lambda()>::<lambda>(<lambda()>&&)
prog.cpp:3:88: error: no match for 'operator=' in '((MyClass*)this)->MyClass::t = t'
prog.cpp: In function 'int main()':
prog.cpp:5:27: error: no matching function for call to 'MyClass::MyClass(main()::<lambda()>)'
prog.cpp:3:48: note: candidates are: MyClass::MyClass(<lambda()>)
prog.cpp:3:14: note: MyClass::MyClass(const MyClass&)
Does anyone know how to do this?
If you want a class member to be a lambda expression, consider using the std::function<> wrapper type (from the <functional> header), which can hold any callable function. For example:
std::function<int()> myFunction = [] { return 0; }
myFunction(); // Returns 0;
This way, you don't need to know the type of the lambda expression. You can just store a std::function<> of the appropriate function type, and the template system will handle all the types for you. More generally, any callable entity of the appropriate signature can be assigned to a std::function<>, even if the the actual type of that functor is anonymous (in the case of lambdas) or really complicated.
The type inside of the std::function template should be the function type corresponding to the function you'd like to store. So, for example, to store a function that takes in two ints and returns void, you'd make a std::function<void (int, int)>. For a function that takes no parameters and returns an int, you'd use std::function<int()>. In your case, since you want a function that takes no parameters and returns void, you'd want something like this:
class MyClass {
public:
std::function<void()> function;
MyClass(std::function<void()> f) : function(f) {
// Handled in initializer list
}
};
int main() {
MyClass([] {
printf("hi")
}) mc; // Should be just fine.
}
Hope this helps!
The only way I can think of to store a lambda in a class is to use a template with a helper make_ function:
#include <cstdio>
#include <utility>
template<class Lambda>
class MyClass {
Lambda _t;
public:
MyClass(Lambda &&t) : _t(std::forward<Lambda>(t)) {
_t();
}
};
template<class Lambda>
MyClass<Lambda> make_myclass(Lambda &&t) {
return { std::forward<Lambda>(t) };
}
int main() {
make_myclass([] {
printf("hi");
});
}
In case of [] (empty capture) simple function pointer can be used. Declaration syntax is ReturnType (*pointer_name) (Arg1T, Arg2T); for pointer, ReturnType (&ref_name) (/*void*/); for reference (can't be null). Lambda with empty capture block is implicitly convertible to function pointer with same signature. And std::function have runtime and size (it is at least three times larger) overhead.
struct S
{
void (*f_p)() {}; // `{}` means `= nullptr`;
};
int main()
{
S s { [] { std::cout << "Lambda called\n"; }};
s.f_p();
S s2;
if (s2.f_p) // check for null
s.f_p();
s2.f_p = [] { std::cout << "Lambda2 called\n"; };
s2.f_p();
s2.f_p = std::terminate; // you can use regular functions too
s2.f_p();
}
Output
Lambda called
Lambda2 called
terminate called without an active exception
Please can someone help explain why I get an error when compiling the following code using Xcode 5.1 on OS X.
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn).
#include <vector>
#include <functional>
void func1(const std::string& value)
{
// ...
}
void func2(const std::string& value, int min, int max)
{
// ...
}
class X
{
public:
void x1(const std::string& value)
{
// ...
}
void x2(const std::string& value, int min, int max)
{
// ...
}
};
const std::vector<std::function<void(std::string)>> functions
{
func1,
std::bind(func2, std::placeholders::_1, 5, 6),
std::mem_fn(&X::x1), // compiler error
};
The error reported is:
no matching constructor for initialization of 'const std::vector<std::function<void (std::string)> >'
const std::vector<std::function<void(std::string)>> functions
Furthermore, I would like to add X::x2 to the vector. How would I do that?
Thanks.
What std::mem_fn does, it returns some unspecified object callable with an additional first argument of a pointer or reference type (or even a smart pointer type) same as the type that member function or member variable that is passed in belongs to (all other arguments are forwarded). That means you could store that object in a function wrapper like below:
std::function<void(X*,const std::string&)> f = std::mem_fn(&X::x1);
and then call it with an actual argument:
X x{};
f(&x, "foo"); // or std::mem_fn(&X::x1)(&x, "foo");
which is same as:
(&x)->x1("foo");
In other words, this is most probably not what you wanted while storing that callable object in a std::vector of std::function<void(const std::string&)>. Instead of adding the additional first argument, you should rather bind it with a context for which that function will be invoked:
X x{}; // object in context of which the function will be called
const std::vector<std::function<void(std::string)>> functions
{
func1,
std::bind(func2, std::placeholders::_1, 5, 6),
std::bind(&X::x1, &x, std::placeholders::_1),
// ~~~~~~~~^ ~~~~~^ ~^ ~~~~~~~~~~^
// bind function with object x and actual argument to be forwarded
};
DEMO
8.3.5/8 Functions [dcl.fct] says
[...] Functions shall not have a return type of
type array or function, although they may have a return type of type pointer or reference to such things. [...]
Why so explicit of a rule? Is there some syntax that would even allow returning a function as opposed to a function pointer?
Am I miss-interpreting the quote?
typedef void (*fp)();
void foo(){}
fp goo()
{
return foo; //automatically converted to function pointer
}
This is quite a contrived example of a function trying to return a function:
void foo() { }
template<typename T>
T f() { return foo; }
int main(){
f<decltype(foo)>();
}
This is the error I get from Clang 3.2:
Compilation finished with errors:
source.cpp:7:5: error: no matching function for call to 'f'
f<decltype(foo)>();
^~~~~~~~~~~~~~~~
source.cpp:4:3: note: candidate template ignored: substitution failure
[with T = void ()]: function cannot return function type 'void ()'
T f() { return foo; }
~ ^
1 error generated.
Is there some syntax that would even allow returning a function as opposed to a function pointer?
A syntax? Sure there is:
using fun = int (int);
fun function_that_returns_a_function();
That doesn’t compile because the rule in §8.3.5/8 forbids it. I don’t know why the rule specifically exists – but consider that the type “function” doesn’t have any size so you cannot create objects of function type in C++.
I know this probably does not answer your question completely but it does so partially
You can return a function from another function (that's what lambdas are)
std::function<int (int)> retLambda() {
return [](int x) { return x; };
}
class A {
public:
std::function<void(int)> f_;
void print_num(int i) {
cout << i;
}
void setFuntion(std::function<void(int)> f) {
f_=f;
}
void run() {
setFunction(print_num);
}
};
this doesn't work. i get note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘std::function<void(int)>’ and other errors.
If I put the definition of print_num outside of the class. everything works. i tried adding &A::, A:: and this. nothing helped.
print_num is a non-static member function, which means that it has an implicit first argument of type A*. You can, for instance, pass that by using a lambda:
void run() {
auto myself = this;
setFunction( [myself] (int i) { myself->print_num (i); } );
}
or use bind, see here
c++ Trouble casting overloaded function: <unresolved overloaded function type>
What's the difference between
typedef void (&FunctionTypeR)();
vs
typedef void (FunctionType)();
Is the second also a reference to function? Is FunctionTypeR equivalent to FunctionType& when used as the type of an argument?
For
void foo(FunctionType bar)
Does the runtime makes a copy of the argument bar (a function) when foo is invoked?
The difference is that you cannot create objects of function type, but you can create of objects of function pointer type, and function reference type.
That means if you've a function, say f() as:
void f(){}
then here is what you can do, and what you cannot do:
FunctionType fun1 = f; //error - cannot create object of function type
FunctionType *fun2 = f; //ok
FunctionTypeR fun3 = f; //ok
Test code:
typedef void (&FunctionTypeR)();
typedef void FunctionType();
void f(){}
int main() {
FunctionType fun1 = f; //error - cannot create object of function type
FunctionType *fun2 = f; //ok
FunctionTypeR fun3 = f; //ok
return 0;
}
Now see the compilation error (and warnings):
prog.cpp: In function ‘int main()’:
prog.cpp:7: error: function ‘void fun1()’ is initialized like a variable
prog.cpp:8: warning: unused variable ‘fun2’
prog.cpp:9: warning: unused variable ‘fun3’
Online demo : http://ideone.com/hpTEv
However, if you use FunctionType (which is a function type) in a function parameter list as:
void foo(FunctionType bar);
then it's equivalent to
void foo(FunctionType * bar);
That means, no matter what you write, you can call the function using bar as:
bar(); //ok
(*bar)(); //ok
That is, you can write this:
void h(FunctionType fun) { fun(); }
void g(FunctionType fun) { (*fun)(); }
Demo : http://ideone.com/kwUE9
This is due to function type to function pointer type adjustment; that is, the function type is adjusted to become a pointer to function type:
Function type | Function pointer type (adjusted type)
void () | void (*)()
void (int) | void (*)(int)
int (int,int) | int (*)(int,int)
.... | ... so on
The C++03 Standard says in §13.1/3,
Parameter declarations that differ only in that one is a function type and the other is a pointer to the same function type are equivalent. That is, the function type is adjusted to become a pointer to function type (8.3.5).
[Example:
void h(int());
void h(int (*)()); // redeclaration of h(int())
void h(int x()) { } // definition of h(int())
void h(int (*x)()) { } // ill-formed: redefinition of h(int())
]
And if you use `FunctionTypeR (which is a function reference type) as:
void foo(FunctionTypeR bar);
then it's equivalent to:
void foo(FunctionType * & bar);
And,
void h(FunctionTypeR fun) { fun(); }
void g(FunctionTypeR fun) { (*fun)(); }
Demo : http://ideone.com/SmtQv
Interesting part...
You can use FunctionType to declare a function (but not to define it).
For example,
struct A
{
//member function declaration.
FunctionType f; //equivalent to : void f();
};
void A::f() //definition
{
std::cout << "haha" << std::endl;
}
//forward declaration
FunctionType h; //equivalent to : void h();
int main() {
A a;
a.f(); //call member function
h(); //call non-member function
}
void h() //definition goes below main()
{
std::cout <<"hmmm.." << std::endl;
}
Demo : http://ideone.com/W4ED2