std :: initializer_list作为构造函数的模板参数 [英] std::initializer_list as template argument for constructor

查看:232
本文介绍了std :: initializer_list作为构造函数的模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Consider a class which inherits from a std container with a template constructor which calls the underlying constructor of the container. This template constructor works for the simple copy and move constructor but not for the 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?并且有可能这样做吗?

If I remove the initializer_list constructor vdi2 won't compile. So my question: Why is the initializer_list not deduced by the template constructor? And is it possible to do so?

推荐答案

为什么模板化构造函数没有推导出initializer_list?

why is the initializer_list not deduced by the templated constructor?

原因是{1,2,3,4,5,6,7,8,9}只是一个没有类型的拼合构造.因此,编译器无法为此合意构造推断类型T,并且第一个构造函数失败.

The reason is that {1,2,3,4,5,6,7,8,9} is just a synctatic construct that doesn't have a type. Therefore, the compiler cannot deduce a type T for this synctatic construct and the first constructor fails.

但是,根据特殊的标准规则,std::initializer_list<T>(除其他事项外)可以从这种合意性构造中构造出来,并且T可以推导为int.因此,第二个构造函数起作用.

However, by special Standard rules std::initializer_list<T> (among other things) can be construct from this synctatic construct and T can be deduced to int. Hence the second constructor works.

通过与函数模板参数类型推导比较,与

By constrast with function template argument type deduction, with

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

编译器将x的类型设置为std::initializer_list<int>.还有一些特殊的标准规则规定必须如此.严格地说,这不是 类型推断,因为如上所述,{1,2,3,4,5,6,7,8,9}没有要推断的类型. (这里唯一发生的类型推导是std::initializer_list<T>中的T = int.)在这里,编译器选择(不推论)x的类型为std::initializer_list<int>.在任何情况下,使用滥用语言将x的类型推导为std::initializer_list<int>都是没有害处的.

the compiler sets the type of x to be std::initializer_list<int>. There are also special Standard rules that says it must be so. Strictly speaking this is not type deduction because, as said above, {1,2,3,4,5,6,7,8,9} doesn't have a type to be deduced. (The only type deduction happening here is T = int in std::initializer_list<T>.) Here the compiler chooses (it doesn't deduce) the type of x to be std::initializer_list<int>. In any case, there's no harm to use the abuse of language of saying that the type of x is deduced to std::initializer_list<int>.

最后,正如DyP在评论中所说,您可能想要的是从基本容器类继承所有构造函数(不仅是带有一个参数的那些构造函数).您可以通过删除当前拥有的所有构造函数并将此行添加到test:

Finally, as DyP said in the comments, what you probably want is inheriting all constructors (not only those taking one argument) from the base container class. You can do this by removing all the constructors that you currently have and add just this line to test:

using container_type::container_type;

这篇关于std :: initializer_list作为构造函数的模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆