为什么从可变参数继承时需要转发构造函数参数?
Why need to forward constructor parameters when inheriting from variadic arguments?
我知道标题完全没有意义,我正在挑战你根据问题编辑它。
我有以下包装 lambda 表达式(从它们继承)并使用它们的 operator()'s
进行重载。
#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);
}
代码抄自《C++设计模式》一书(强烈推荐)
而且我观察到构造函数参数是多余的,因为我们只需要基数 类 的 operator()'s
。
所以我做了一个确切的例子,但使用了更温和的构造函数:
OverloadSet(F&&... f) {}
从这一点来看,我很难理解这个程序是否格式错误,因为不同的编译器有不同的反应:
海湾合作委员会 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(最新)
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(启用 C++20)
Compiles and prints:
int 3
double 3.2
所以问题是:
- 程序格式是否正确?
- 如果不是,如果我们只使用 operator() 的基础 类,为什么我们需要转发参数?
我猜 lambda 没有默认构造函数。
更像这样:
class A {
public:
A(int a) {}
};
class B {
public:
B(double b) {}
};
class C : public A, public B {
public:
C() {} // error
};
我知道标题完全没有意义,我正在挑战你根据问题编辑它。
我有以下包装 lambda 表达式(从它们继承)并使用它们的 operator()'s
进行重载。
#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);
}
代码抄自《C++设计模式》一书(强烈推荐)
而且我观察到构造函数参数是多余的,因为我们只需要基数 类 的 operator()'s
。
所以我做了一个确切的例子,但使用了更温和的构造函数:
OverloadSet(F&&... f) {}
从这一点来看,我很难理解这个程序是否格式错误,因为不同的编译器有不同的反应:
海湾合作委员会 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(最新)
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(启用 C++20)
Compiles and prints:
int 3
double 3.2
所以问题是:
- 程序格式是否正确?
- 如果不是,如果我们只使用 operator() 的基础 类,为什么我们需要转发参数?
我猜 lambda 没有默认构造函数。
更像这样:
class A {
public:
A(int a) {}
};
class B {
public:
B(double b) {}
};
class C : public A, public B {
public:
C() {} // error
};