[英]deduce the type of tuple elements in c++11
I have the following code. 我有以下代码。
template <typename... Types>
void print_tuple(const std::tuple<Types&&...>& value)
{
std::cout << std::get<0>(value) << "," << std::get<1>(value) << std::endl;
}
print_tuple(std::forward_as_tuple("test",1));
which compiler complains about 哪个编译器抱怨
error: invalid initialization of reference of type ‘const std::tuple<const char (&&)[5], int&&>&’ from expression of type ‘std::tuple<const char (&)[5], int&&>’
print_tuple(std::forward_as_tuple("test",1));
why does compiler deduce the type of the first element in the tuple to be const char (&&)[5]? 为什么编译器会将元组中第一个元素的类型推断为const char(&&)[5]?
Generally speaking, for deduction to succeed, the argument needs to have the same general form as the parameter. 一般来说,为了使演绎成功,参数需要具有与参数相同的一般形式。 There are some exceptions where
T &&
can be deduced from U &
(by selecting T = U &
), but no such exception was specified for this case. 有一些例外,其中
T &&
可以从U &
推导出(通过选择T = U &
),但没有为此案例指定此类例外。
14.8.2.5 Deducing template arguments from a type [temp.deduct.type]
14.8.2.5从类型[temp.deduct.type]中推导出模板参数
8 A template type argument
T
, a template template argumentTT
or a template non-type argumenti
can be deduced ifP
andA
have one of the following forms:8如果
P
和A
具有以下形式之一,则可以推导出模板类型参数T
,模板模板参数TT
或模板非类型参数i
:[...]
[...]
T&
T&&
[...]
[...]
It's not exactly clear, but this requires P
(the parameter) and A
(the argument) to both have the same form. 它并不完全清楚,但这需要
P
(参数)和A
(参数)都具有相同的形式。 They need to both be of the T&
form, or both of the T&&
form. 他们既需要
T&
形式,也需要T&&
形式。 The exceptions, the circumstances where T &&
can be deduced from U &
, are done by changing T &&
to plain T
before the matching takes place, in limited circumstances: 例外情况,
T &&
可以从U &
推导出来的情况是通过在匹配发生之前将T &&
更改为plain T
来完成的,在有限的情况下:
10 Similarly, if
P
has a form that contains(T)
, then each parameter typeP i
of the respective parameter-type-list ofP
is compared with the corresponding parameter typeA i
of the corresponding parameter-type-list ofA
.10类似地,如果
P
具有包含形式(T)
然后每个参数类型P i
的相应的参数类型列表的P
与对应的参数进行比较型A i
的相应的参数类型列表的A
。 IfP
andA
are function types that originated from deduction when taking the address of a function template (14.8.2.2) or when deducing template arguments from a function declaration (14.8.2.6) andP i
andA i
are parameters of the top-level parameter-type-list ofP
andA
, respectively,P i
is adjusted if it is an rvalue reference to a cv-unqualified template parameter andA i
is an lvalue reference, in which case the type ofP i
is changed to be the template parameter type (ie,T&&
is changed to simplyT
).如果
P
和A
是在获取函数模板的地址(14.8.2.2)或从函数声明(14.8.2.6)中推导出模板参数时起源于演绎的函数类型,并且P i
和A i
是顶部的参数 -P
和A
级别参数类型列表 ,如果它是对cv非限定模板参数的右值引用并且A i
是左值参考,则调整P i
,在这种情况下,P i
的类型被改变为模板参数类型(即T&&
更改为T
)。 [...][...]
and 和
14.8.2.1 Deducing template arguments from a function call [temp.deduct.call]
14.8.2.1从函数调用中减去模板参数[temp.deduct.call]
3 [...] If
P
is an rvalue reference to a cv-unqualified template parameter and the argument is an lvalue, the type "lvalue reference toA
" is used in place ofA
for type deduction.3 [...]如果
P
是对cv-nonqualified模板参数的rvalue引用,并且参数是左值,则使用类型“对A
左值引用”代替A
进行类型推导。 [...][...]
but no similar exception applies to your scenario. 但是没有类似的例外适用于您的方案。
It's this same principle that renders 这就是渲染的原理
template <typename T> struct S { };
template <typename T> void f(S<const T>) { }
int main() { f(S<void()>()); }
invalid: const T
cannot be deduced from void()
, even though T = void()
would give exactly that result, and calling f<void()>
would succeed. invalid:
const T
不能从void()
推导出来,即使T = void()
会给出完全相同的结果,并且调用f<void()>
也会成功。
Wintermute's deleted answer showed that you can use Wintermute删除的答案显示你可以使用
template <typename... Types> // vv-- change here void print_tuple(const std::tuple<Types...>& value)
instead: this allows Types
to be deduced as lvalue references, as rvalue references, or as non-references, depending on the type of value
. 相反:这允许将
Types
推导为左值引用,rvalue引用或非引用,具体取决于value
的类型。
Did you intend to use &&
in std::tuple<Types&&...>
as a universal reference? 您是否打算在
std::tuple<Types&&...>
使用&&
作为通用引用? This is not universal reference; 这不是普遍的参考; it is rvalue reference and can only bind to rvalues.
它是rvalue引用,只能绑定到rvalues。 You can do like this to check what kind of reference it is:
您可以这样做以检查它是什么类型的引用:
template<typename T>
class TD;
Then define your template function: 然后定义模板函数:
template <typename... Types>
void print_tuple(const std::tuple<Types&&...>& value)
{
TD<decltype(value)> a;
std::cout << std::get<0>(value) << "," << std::get<1>(value) << std::endl;
}
Then you will see the compilation error like: 然后你会看到编译错误,如:
implicit instantiation of undefined template 'TD<const std::__1::tuple<std::__1::basic_string<char> &&, int &&> &>'
You can see that even for the int
type, it deduces to be rvalue reference. 你可以看到,即使对于
int
类型,它也推导为rvalue引用。 Rvalue references cannot bind to lvalues. Rvalue引用不能绑定到左值。 You can try that by calling:
你可以通过调用来尝试:
int i = 1;
print_tuple(std::forward_as_tuple(i,1)); // error.
Therefore, it is correct that const char(&&)[5]
is deduced, and a string literal cannot be converted to const char(&&)[5]
. 因此,推导出
const char(&&)[5]
是正确的,并且字符串文字不能转换为const char(&&)[5]
。 If you call print_tuple
like: 如果你调用
print_tuple
:
print_tuple(std::forward_as_tuple(string("test"),1));
It will work. 它会工作。 Now the type is
tuple<string&&, int&&>
. 现在类型是
tuple<string&&, int&&>
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.