使用可变参数模板模板输入演绎和参数传递

时间:2012-11-24 00:56:14

标签: c++ templates c++11 rvalue-reference template-templates

由于可变参数模板,我前一段时间实现了C ++等效的Python链函数。该函数用于连续迭代许多容器。这是使用名为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得到以下错误:

  

在函数'int main()'中:

     

错误:没有匹配函数来调用'chain(std :: vector&amp;,std :: list&amp;)'

     

注意:候选人是:

     

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

     

注意:参数2从“std::list<int>”到“std::list<int>&&”没有已知转换

     

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

     

注意:参数2从“std::list<int>”到“std::list<int>&&”没有已知转换

     

错误:无法推断'auto&amp;'来自''

似乎问题来自于传递给rvalue引用的函数的参数。但是,我真的不明白为什么我的第一个版本工作正常,并注意使用模板模板。

1 个答案:

答案 0 :(得分:5)

您的问题是T&&模板魔法仅适用于类型参数(如果需要,它可以通过推导T作为例如。int& - 适用于左值参数)。它不适用于模板模板参数,其中实际类型为X<T>&& - X在这种情况下必须是类模板,而不是类似“引用类模板”。所以最后你必须传递一个rvalue-reference,你不能从lvalue(变量)隐式得到它。

那就是说,我建议你回复你之前的代码并检查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