【问题标题】:std::initializer_list as template argument for constructorstd::initializer_list 作为构造函数的模板参数
【发布时间】:2013-10-29 04:14:59
【问题描述】:

考虑一个从 std 容器继承的类,该类具有调用容器底层构造函数的模板构造函数。此模板构造函数适用于简单的复制和移动构造函数,但不适用于 initializer_list ctor。

template<typename container_T>
class test : public container_T {
public:
  using container_type = container_T;

  test() {} 

  // templated constructor
  template<typename T>
  test(T t)
    : container_T(t) {}

   // without this it won't compile
  test(std::initializer_list<typename container_T::value_type> l)
    : container_T(l) {}
};

int main() {    
  test<std::deque<int>> vdi1;
  test<std::deque<int>> vdi2({1,2,3,4,5,6,7,8,9});

  std::cout << "vdi2 before:" << std::endl;
  for(auto it : vdi2)
    std::cout << it << std::endl;

  test<std::deque<int>> vdi3(std::move(vdi2));

  std::cout << "vdi2 before:" << std::endl;
  for(auto it : vdi2)
    std::cout << it << std::endl;

  std::cout << "vdi3 before:" << std::endl;
  for(auto it : vdi3)
    std::cout << it << std::endl;

  return 0;
}

如果我删除 initializer_list 构造函数 vdi2 将无法编译。所以我的问题是:为什么模板构造函数没有推断出initializer_list?有可能吗?

【问题讨论】:

  • 实际上,它不是复制或移动,它们是隐式声明的,除了你的ctor。它不适用于initializer_lists,因为它们不能/不能被推断出来。
  • 你为什么不使用继承的ctors? using container_T::container_T;Live example
  • @DyP 为什么要继承复制或移动 ctor?
  • 编辑过的评论(..还是少了一个字:其实不是抄袭或搬家_ctor_)。我的意思是:ctor 模板绝不是复制或移动 ctor。

标签: c++ c++11 constructor initializer-list type-deduction


【解决方案1】:

为什么初始化器列表不是由模板化构造函数推导出来的?

原因是{1,2,3,4,5,6,7,8,9} 只是一个没有类型的同步构造。因此,编译器无法为这个同步构造推导出类型T,并且第一个构造函数失败。

但是,通过特殊的标准规则std::initializer_list&lt;T&gt;(除其他外)可以从这个同步结构构造,T 可以推导出为int。因此第二个构造函数起作用了。

与函数模板参数类型推导对比,与

auto x = {1,2,3,4,5,6,7,8,9};

编译器将 x 的类型设置为std::initializer_list&lt;int&gt;。还有一些特殊的标准规则规定必须如此。严格来说,这是 not 类型推导,因为如上所述,{1,2,3,4,5,6,7,8,9} 没有要推导的类型。 (这里发生的唯一类型推导是std::initializer_list&lt;T&gt; 中的T = int。)这里编译器选择(它不推导)x 的类型为std::initializer_list&lt;int&gt;。无论如何,滥用语言将x的类型推导出为std::initializer_list&lt;int&gt;是没有害处的。

最后,正如 DyP 在 cmets 中所说,您可能想要的是从基容器类继承所有构造函数(不仅是那些接受一个参数的构造函数)。您可以通过删除当前拥有的所有构造函数并将这一行添加到test 来做到这一点:

using container_type::container_type;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-31
    • 2013-06-14
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多