[英]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: 我认为这样做可以确保我以前的主
list
和vector
共享同一类型,但是我从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.