推导出c ++ 11中元组元素的类型

时间:2015-03-21 14:25:11

标签: c++ c++11

我有以下代码。

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

哪个编译器抱怨

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

为什么编译器会将元组中第一个元素的类型推断为const char(&amp;&amp;)[5]?

2 个答案:

答案 0 :(得分:2)

一般来说,为了使演绎成功,参数需要与参数具有相同的一般形式。有一些例外情况可以从T &&推断U &(通过选择T = U &),但没有为此案例指定此类例外。

  

14.8.2.5从类型[temp.deduct.type]中扣除模板参数

     

8如果TTT,可以推导出模板类型参数i,模板模板参数P或模板非类型参数A有下列形式之一:

     

[...]

     

T&
  T&&

     

[...]

它不完全清楚,但这要求P(参数)和A(参数)都具有相同的形式。它们都需要T&形式,或两者都是T&&形式。例外情况,T &&可以从U &推断T &&的情况是通过在匹配发生之前将T更改为普通P来完成的,在有限的情况下:

  

10同样,如果(T)的表单包含Pi,那么{{>参数类型列表的每个参数类型P Ai 1}}与A的相应参数类型列表的相应参数类型P进行比较。如果APi是在获取函数模板的地址(14.8.2.2)时或从函数声明(14.8.2.6)和{{1中推导出模板参数时 - 来自演绎的函数类型和   Ai分别是PA的顶级参数类型列表的参数,Pi如果是Ai则会调整rvalue对cv-unqualified模板参数的引用和Pi是左值引用,在这种情况下,T&&的类型被更改为模板参数类型(即,T更改为只需P)。 [...]

  

14.8.2.1从函数调用中减去模板参数[temp.deduct.call]

     

3 [...]如果A是对cv-nonqualified模板参数的右值引用,并且参数是左值,则类型&#34;左值引用A&#34 ;用于代替template <typename T> struct S { }; template <typename T> void f(S<const T>) { } int main() { f(S<void()>()); } 进行类型扣除。 [...]

但没有类似的例外适用于您的方案。

呈现

的原理相同
const T

无效:void()无法从T = void()推断出来,即使f<void()>会给出确切的结果,并且调用template <typename... Types> // vv-- change here void print_tuple(const std::tuple<Types...>& value) 也会成功。

Wintermute的删除答案显示您可以使用

Types

相反:这允许value被推导为左值引用,rvalue引用或非引用,具体取决于{{1}}的类型。

答案 1 :(得分:0)

您是否打算在&&中使用std::tuple<Types&&...>作为通用参考?这不是普遍的参考;它是rvalue引用,只能绑定到rvalues。您可以这样做以检查它是什么类型的引用:

template<typename T>
class TD;

然后定义模板功能:

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

然后您将看到编译错误,如:

implicit instantiation of undefined template 'TD<const std::__1::tuple<std::__1::basic_string<char> &&, int &&> &>'

您甚至可以看到int类型,它推导为右值参考。 Rvalue引用不能绑定到左值。你可以通过调用:

来尝试
int i = 1;
print_tuple(std::forward_as_tuple(i,1)); // error.

因此,推导const char(&&)[5]是正确的,并且字符串文字无法转换为const char(&&)[5]。如果您致电print_tuple,请致电:

print_tuple(std::forward_as_tuple(string("test"),1));

它会起作用。现在类型为tuple<string&&, int&&>