可变参数类模板和可变参数构造函数

Variadic class template and variadic constructor

本文关键字:参数 变参 构造函数      更新时间:2023-10-16

在Jason Turner的每周第48集C++有以下代码:

template<typename ... B>
struct Merged : B...
{
  template <typename ... T>
  Merged(T && ... t) : B(std::forward<T>(t))...
  {  }
  using B::operator()...;
};

它在 gcc 7.1 上失败并显示以下内容:

error: mismatched argument pack lengths while expanding 'B'

扩展 B 的正确方法是什么?

(顺便说一句,在上面的链接中,代码似乎使用一些 7.0 快照编译(。

编辑1:

如@Jarod42所述,它将使用充当函子的结构进行编译。实际视频使用lambda,它似乎在那里中断。

auto l1 = [] { return 4 ; };
auto l2 = [](const int i) { return i * 10; };
// This would work, S1, S2 are just functors structs
Merged<S1, S2> merged1(42, "hello");
// This fails
Merged merged2 = Merged(l1, l2);

编辑2:

似乎用户定义的演绎指南在这里不起作用。

template <typename ... T>
Merged(T...) -> Merged<std::decay_t<T>...>;

以上应启用以下内容:

Merged merged(l1, l2);

但事实并非如此。似乎您必须将类型传递给合并<>

Merged<t1, t2> merged(l1, l2);

这可能不是本教程想要演示的内容。

似乎

不需要在这里定义任何构造函数,而是只使用 C++17 聚合:

template<typename ... B>
struct Merged : B...
{
//  This is not needed, it would actually render this class
//  to be a non-aggregate one.
//  template <typename ... T>
//  Merged(T && ... t) : B(std::forward<T>(t))...
//  {  }
    using B::operator()...;
};
// C++17 class deduction guidance (user defined)
template <typename ... T>
Merged(T...) -> Merged<T...>;
int main()
{
    auto l1 = [] { return 4 ; };
    auto l2 = [](const int i) { return i * 10; };
    // Note here, using {} for initializing an aggregate
    Merged merged{l1, l2};
}

请注意 C++17 类推导用户定义的指南,以及使用 {} 初始化聚合。

不需要构造函数。如果我们拥有它,这个类将不再是聚合,用于初始化的语法将停止工作。

如果参数包的大小应该相等,我们可以强制执行 std::enable_if

template<typename ... B>
struct Merged : B...
{
  template <typename ... T,
            typename = typename std::enable_if_t<sizeof...(T) == sizeof...(B)>>
  Merged(T && ... t) : B(std::forward<T>(t))...
  {  }
  using B::operator()...;
};

这与用户定义的扣除指南一起似乎有效。

template <typename ... T>
Merged(T&& ... t) : B(std::forward<T>(t))...
{}

sizeof...(T)应等于sizeof...(B):您必须按基础提供一个参数。

然后它起作用了。

如果您不提供相同数量的参数,则会出现类似于以下内容的错误:

错误:扩展"B"时参数包长度不匹配