2012-11-24 39 views
2

通过我实现了Python的连锁功能的C++相当于前一段时间由于可变参数模板。该函数用于连续遍历许多容器。下面是使用一个名为ChainedObject发电机的功能,不管它是旧的工作版本:类型推演和论证与可变参数模板模板

template<typename... Iterables> 
auto chain(Iterables&&... iters) 
    -> ChainObject<Iterables...> 
{ 
    return /* ... */; 
} 

和相应的主:

int main() 
{ 
    std::vector<int> vec = { 1, 2, 3, 4, 5 }; 
    std::list<int> li = { 6, 7, 8, 9, 10, 11, 12, 13 }; 
    for (auto& i: chain(vec, li)) 
    { 
     // You can edit a range of iterables 
     // as if there was only one of them. 
     i *= 5; 

     std::cout << i << std::endl; 
    } 
    return 0; 
} 

这主要工作得很好。我们不在乎ChainObject中存在什么问题,所以让我们来看看它。我试图用模板模板,以确保所使用的不同集合有同样的value_type和修改功能chain方式如下:

template<typename T, template<typename...> class... Iterables> 
auto chain(Iterables<T>&&... iters) 
    -> ChainObject<T, Iterables...> 
{ 
    return /* ... */; 
} 

我认为这会做的伎俩,以确保我以前主要的listvector共享相同的类型,而是,我从GCC 4.7.1以下错误:

In function 'int main()':

error: no matching function for call to 'chain(std::vector&, std::list&)'

note: candidates are:

note: ChainObject<T, Iterables ...> chain(Iterables<T>&& ...) [with T = int; Iterables = {std::vector, std::list} ]

note: no known conversion for argument 2 from ' std::list<int> ' to ' std::list<int>&& '

note: ChainObject<T, Iterables ...> chain(Iterables<T>&& ...) [with T = int; Iterables = {std::vector, std::list}]

note: no known conversion for argument 2 from ' std::list<int> ' to ' std::list<int>&& '

error: unable to deduce 'auto&' from ''

看来,问题来自于通过采取右值引用的函数的参数。但是,我真的不明白为什么我的第一个版本运行良好,并注意使用模板模板。

+0

您是否尝试过通过左值引用,而不是右值吗? –

+0

请勿将模板模板与容器组合使用。一旦使用分配器就会失败。只需检查嵌套的'value_type'是否相等。 – pmr

回答

5

你的问题是T&&模板魔术仅适用于类型参数(它的工作方式推导T作为例如int&如果需要的话 - 对于左值参数)。 X必须在这种情况下,一个类模板,而不是像“参考到类模板” - 它不能为模板模板参数,在实际的类型是X<T>&&工作。所以最后你必须传递一个右值引用,你不能从一个左值(变量)中隐式地得到。这就是说,我建议你恢复到以前的代码,并检查value_type与SFINAE是否相同(或兼容,等等,不管你会怎么做)。

粗码草图(严格平等):

template <class ... Ts> struct all_types_equal 
{ 
    static const bool value = false; 
}; 

template <class T> 
struct all_types_equal<T> 
{ 
    static const bool value = true; 
}; 
template <class T, class ... Rest> 
struct all_types_equal<T, T, Rest...> 
{ 
    static const bool value = all_types_equal<T, Rest...>::value; 
}; 

template<typename... Iterables> 
auto chain(Iterables&&... iters) 
    -> typename std::enable_if<all_types_equal<Iterable::value_type...>::value, ChainObject<Iterables...> >::type 
+0

非常感谢。看来我仍然有很多要学习C++。我会恢复到使用普通的旧'enable_if'然后:) – Morwenn

+0

我想,一个正确的返回类型'类型名称的std :: enable_if ::类型:: value_type的... > :: value,ChainObject > :: type'。 – Morwenn