I know the title makes exactly 0 sense, I am challenging you to edit it according to the question.
I have the following wrapper that wraps lambda expressions (inherits from them) and uses their operator()'s
for overloading.
#include <iostream>
template<typename... F>
struct OverloadSet : public F...
{
OverloadSet(F&&... f) : F(std::forward<F>(f))...{}
using F::operator() ...;
};
template<typename... T>
auto overloads(T...t) {
return OverloadSet<T...>(std::forward<T>(t)...);
}
auto s = overloads(
[](int s) {std::cout << typeid(s).name() << " " << s << std::endl; },
[](double d) {std::cout << typeid(d).name() << " " << d << std::endl; }
);
int main()
{
auto s = overloads(
[](int s) {std::cout<<typeid(s).name()<<" " << s << std::endl; },
[](double d) {std::cout << typeid(d).name() << " "<< d << std::endl; }
);
s(3);
s(3.2);
}
The code is copied from C design patterns book (highly recommend)
And I have made my observation that the constructor params are redundant as we only need operator()'s
of base classes.
So I made the exact example but with more modest constructor:
OverloadSet(F&&... f) {}
From this point I have problems to understand whether this program is ill formed or not because have different reaction from different compilers:
GCC 11.2
Output of x86-64 gcc 11.2 (Compiler #1)
In instantiation of 'OverloadSet<F>::OverloadSet(F&& ...) [with F = {<lambda(int)>, <lambda(double)>}]':
required from 'auto overloads(T ...) [with T = {<lambda(int)>, <lambda(double)>}]'
required from here
error: use of deleted function '<lambda(int)>::<lambda>()'
Clang (latest)
error: constructor for 'OverloadSet<(lambda at <source>:16:2),
(lambda at <source>:17:2)>' must explicitly initialize the base class '(lambda at <source>:16:2)' which does not have a default constructor
OverloadSet(F&&... f) {}// F(std::forward<F>(f))...{}
MSVC2019 (with C 20 enabled)
Compiles and prints:
int 3
double 3.2
So the questions are:
- Whether the program is well formed?
- If not, why do we need to forward arguments if we only use operator()'s of base classes?
CodePudding user response:
The lambda does not have a default constructor, I guess.
It is more like this:
class A {
public:
A(int a) {}
};
class B {
public:
B(double b) {}
};
class C : public A, public B {
public:
C() {} // error
};