2013-10-20 124 views
4

我有一个继承自std容器的类。现在我有一个模板化的构造函数,它调用容器的基础构造函数。这个模板化构造函数适用于简单复制和移动构造函数,但不适用于initializer_list之一。 std :: initializer_list作为构造函数的模板参数

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不能由模板化的构造函数推导出来?有可能这样做吗?

+0

其实,它不是一个复制或移动,他们是隐式声明的,除了你的构造函数。它不适用于'initializer_list's,因为它们不能被推导出来。 – dyp

+3

为什么你不使用继承ctors? '使用container_T :: container_T;'[Live example](http://coliru.stacked-crooked.com/a/723b9da6b0f8766f) – dyp

+0

@DyP为什么它应该复制或移动ctors? – user1810087

回答

5

为什么initializer_list不能由模板化构造函数推导出来?

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

然而,通过特殊的标准规则std::initializer_list<T>(除其他之外)可以从该合成构建体构建,并且T可以推导为int。因此第二个构造函数有效。

通过与函数模板参数类型推演constrast,与

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>的语言滥用是没有害处的。

最后,正如DyP在注释中所说的,您可能想要的是继承基础容器类中的所有构造函数(不仅是那些带一个参数的构造函数)。您可以通过删除所有你目前已经和刚加入这一行test构造函数做到这一点:

using container_type::container_type; 
相关问题