Variadic class 模板和继承 - 默认编译器生成的构造函数

Variadic class template and inheritance - default compiler generated constructor

下面的代码为什么只使用默认编译器生成的构造函数? 我希望它用于 POD,但下面的结构可能不是 POD,所以它一定是其他东西。

template <typename ... T>
struct C : T ... {
   using T::operator()...;
};

// template class guidance feature of C++17
template <typename ... T>
C(T...) -> C<T...>;

int main(){
   C c { []{}, [](int){} };
   c(3);
}

这个问题是 Jason 的 Turner C++ 周刊第 49/50 期的跟进,他在其中用 std::forward<T>(t)...

定义了一个可变参数构造函数

这里没有构造函数在起作用。由于 C++17 中的三个新功能的融合,此代码有效:

  1. 构造函数的模板参数推导(P0091)。
  2. 扩展聚合初始化(P0017
  3. 现代化使用声明(P0195)。

这一行发生了什么:

C c { []{}, [](int){} };

就是首先,我们通过模板参数推导(1)推导出c确实是C<__lambda1, __lambda2>类型。这是通过使用您的 演绎指南 完成的。

接下来,由于 C<__lambda1, __lambda2> 是一个聚合(由于 (2) 放宽了基础 class 限制 - 你是正确的,在 C++11/14 中不被视为聚合), 我们可以使用 aggregate-initialization 来初始化它。我们使用构造函数。聚合初始化现在使用 base classes 的方式是我们只需要从左到右初始化基数。所以第一个表达式([]{})用于初始化第一个基数class(__lambda1),第二个表达式([](int){})用于初始化第二个基数class(__lambda2)。

最后,调用 c(3) 有效,因为 (3) 允许您简单地编写

using T::operator()...;

将两个 lambda 的调用运算符引入 C 的范围,其中重载解析可以按预期工作。结果是我们调用 __lambda2 的调用运算符,它什么也不做。