I want to create constructors for a class in a way that the compiler trivially create new instances of it when needed.
Here's an example.
class C {
public:
C(int) {}; // int constructor
};
If I then declare a function:
void F(C _c) {};
I can call this one with an int and have the construction of C handled by the compiler:
F(0); // works
What I want to do is to achieve the same thing, but with lambdas as parameters, a few examples:
F([]() {}); //A
F([](int) {}); //B
F([](int)->int { return 0; }); //C
With SFINAE and from what I've learned from another question: Auto-constructor not working with <functional> objects
I managed to sort out a way to create a constructor that matches only a specific lambda signature, it would work out like this:
template<typename F, typename = decltype(function<void(void)>(declval<F&>()))> C(F&& f) {}; //For lambda's like A
template<typename F, typename = decltype(function<void(int)>(declval<F&>()))> C(F&& f) {}; //For lamdba's like B
template<typename F, typename = decltype(function<int(int)>(declval<F&>()))> C(F&& f) {}; //For lambda's like C
Now the problem that I have is that if I add these three definitions at once, I get an error stating that I'm trying to redefine the constructor of C. This is correct because, yeah, the constructor's being defined as C(F&& f) three times, however, how should I let know the compiler to use a different signature for each different case?
The other answer hinted me to look at enable_if and is_convertible but haven't managed to set up a workaround for this issue. Any help is greatly appreciated.
Using: Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Your current problem is that you define 3 times
but with different default argument (to do SFINAE).
You may change to
So you have 3 different signatures:
Based on top answer here, this is what I came up with. It is probably a little crude and can be improved on but the main thing it works (tried on online clang 3.5.0).