简体   繁体   English

使用可变参数模板模板进行类型推导和参数传递

[英]Type deduction and argument passing with variadic template templates

I implemented a C++ equivalent of Python's chain function a while ago thanks to variadic templates. 由于可变参数模板,我不久前实现了C ++等效于Python的链函数。 The function is used to iterate successively through many containers. 该函数用于依次遍历许多容器。 Here is the old working version of the function using a generator named ChainedObject , whatever it is: 这是使用名为ChainedObject的生成器的函数的旧工作版本,无论它是什么:

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

And the corresponding main: 以及对应的主要:

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;
}

That main worked fine. 该主要工作正常。 We don't care what there is in ChainObject for the problem, so let's see it. 我们不在乎ChainObject中存在什么问题,因此让我们来看一下。 I tried to use template templates to ensure that the different collections used had the same value_type and modified the function chain the following way: 我尝试使用模板模板来确保使用的不同集合具有相同的value_type并按以下方式修改了功能chain

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

I thought this would do the trick to ensure the list and vector from my previous main share a same type, but instead, I get the following error from GCC 4.7.1: 我认为这样做可以确保我以前的主listvector共享同一类型,但是我从GCC 4.7.1中得到了以下错误:

In function 'int main()': 在函数'int main()'中:

error: no matching function for call to 'chain(std::vector&, std::list&)' 错误:没有匹配函数可调用'chain(std :: vector&,std :: list&)'

note: candidates are: 注意:候选人是:

note: ChainObject<T, Iterables ...> chain(Iterables<T>&& ...) [with T = int; Iterables = {std::vector, std::list} 注意: ChainObject<T, Iterables ...> chain(Iterables<T>&& ...) [with T = int; Iterables = {std::vector, std::list} ChainObject<T, Iterables ...> chain(Iterables<T>&& ...) [with T = int; Iterables = {std::vector, std::list} ] 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>&& ' 注意:参数2没有从' std::list<int> '到' std::list<int>&& '的已知转换

note: ChainObject<T, Iterables ...> chain(Iterables<T>&& ...) [with T = int; Iterables = {std::vector, std::list}] 注意: ChainObject<T, Iterables ...> chain(Iterables<T>&& ...) [with T = int; Iterables = {std::vector, std::list}] 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>&& ' 注意:参数2没有从' std::list<int> '到' std::list<int>&& '的已知转换

error: unable to deduce 'auto&' from '' 错误:无法从“”推断出“ auto&”

It seems that the problem comes from argument passing to the function taking rvalue references. 看来问题出在传递给带有右值引用的函数的参数上。 However, I really don't understand why my first version worked fine, and note the one using template templates. 但是,我真的不明白为什么我的第一个版本可以正常工作,请注意使用模板模板的版本。

Your problem is that the T&& template magic only works for type parameters (it works by deducing T as eg. int& if needed - for lvalue arguments). 您的问题是T&&模板魔术仅适用于类型参数(如果需要的话,可以通过将T推导出为int&来实现-用于左值参数)。 It can't work for template template arguments, where the actual type is X<T>&& - X must be a class template in this case, not something like "reference-to-class-template". 它不适用于模板模板参数,其中实际类型为X<T>&& -在这种情况下, X必须是类模板,而不是“ reference-to-class-template”之类的东西。 So in the end you have to pass a rvalue-reference, which you cannot implicitly get from a lvalue (variable). 因此,最后您必须传递一个右值引用,您不能从左值(变量)中隐式地获取该引用。

That said, I would suggest you to revert to your earlier code and check that the value_type s are the same (or compatible, etc., whatever gets you going) with SFINAE. 就是说,我建议您恢复到之前的代码,并检查value_type与SFINAE是否相同(或兼容,等等,不管您做什么工作)。

Rough code sketch (for strict equality): 粗略的代码草图(用于严格相等):

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 对可变参数模板和模板类型推导的误解 - Misunderstanding variadic templates and template type deduction 可变参数模板类型推导 - Variadic templates type deduction 可变参数模板的类型推导 - Type deduction for variadic templates 传递初始化程序列表时,可变参数模板参数推导失败 - Variadic template argument deduction fails when passing initializer lists 可变参数模板:迭代类型/模板参数 - Variadic templates: iterate over type/template argument 具有可变参数模板构造函数的推导指南和可变参数类模板-参数包长度不匹配 - Deduction guides and variadic class templates with variadic template constructors - mismatched argument pack lengths Variadic模板和类型扣除问题 - Variadic template and type deduction issue 应用“类模板的模板参数推导”是否应该为可变参数类模板推导出空参数包? - Is “template argument deduction for class templates” supposed to deduce empty parameter packs for variadic class templates? 从同级参数推导模板可变参数 - Template Variadic argument deduction from sibling argument 可变参数模板中的模板参数推导失败 - template argument deduction failed in variadic template
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM