我何时应该使用decltype(x)而不是auto来声明变量的类型?

tem*_*boy 33 c++ c++11

我看到decltype(x)在宏中使用的x是一个变量名,因为在宏内部不知道对象的类型.

例如:

decltype(x) y = expr;
Run Code Online (Sandbox Code Playgroud)

我可以轻松使用auto而不是decltype.那么decltype变量类型声明需要哪些情况而不是auto

Ste*_*sop 19

当所需类型y为:时,您应该使用它:

  • 与类型不同(或可能不同)expr.如果它是相同的那么auto会更简洁.
  • 类似地,对于auto &或类型的其它修改exprauto可表达.

以及以下之一:

  • 依赖于周围代码中的某些东西(即不总是相同的类型)并且难以使用类型特征或类似的东西来编写.这将倾向于在模板代码中发生.可能有一个类型特征可用于从模板参数中获取所需类型,但是再次可能没有这样的特性decltype可以保存您定义一个.
  • 总是相同的类型,(或者以一种易于使用现有类型特征或类似方式表达的方式依赖于模板参数)但是类型是非常冗长的写入,而且可以使用更短更清晰的表达式.

因此,例如更换std::iterator_traits<RandomAccessIterator>::value_typedecltype(*it)很可能是一场胜利,虽然auto不经常处理这样的情况.

主观判断进入"困难","什么是啰嗦"和"什么是明确"这一点,但无论你如何在特定情况下做出这些判断,程序规则都可以相同.


R. *_*des 17

当你想要y总是拥有任何声明的类型x.

  • 这使得`y`始终具有特定类型.不一样. (7认同)
  • @templateboy:谁在乎?你对用例很感兴趣. (6认同)
  • @templateboy你知道`foo(a + b/c)`的返回类型吗? (3认同)

pod*_*ova 17

decltype 当你需要返回一些在编译期间评估的未知类型时变得很方便:

template<class A, class B>
void MultiplyAB(A a, B b, decltype(a*b)& output)
{
    output = a * b;
}
Run Code Online (Sandbox Code Playgroud)

此外,如果您不喜欢引用处理输出的方式,那么您还可以使用迟到的返回类型(并使用decltype):

template<class A, class B>
auto MultiplyAB(A a, B b) -> decltype(a*b)
{
    return a * b;
}
Run Code Online (Sandbox Code Playgroud)

所有这些以及更多内容都由B. Stroustrup在C++ FAQ中描述.


Bri*_*ian 10

在你的问题的背景下,

  • decltype当你想要一个与原始变量具有完全相同类型的新变量时,你应该使用它.

  • auto当您想要某个表达式的值分配给新变量并且您希望或需要推导其类型时,您应该使用它.

decltype(x) y始终声明y与声明的类型完全相同的类型x.特别是:

  • 如果x有类型const inty会有类型const int.
  • 如果x有类型int[100]y会有类型int[100].
  • 如果x有类型int f(int)y会有类型int f(int).是的,这实际上声明了另一个与原始类型相同的函数.
  • 如果x有类型int&y会有类型int&; 如果x有类型,int&&那么y将有类型int&&.

auto y = xy使用以下类型声明,何时x具有以下类型:

  • 如果x有类型const int,那么y将有类型int.也就是说,auto 剥离顶级cv限定符.
  • 如果x有类型int[100],那么y将有类型int*.也就是说,auto 执行数组到指针的转换.[1]
  • 如果x有类型int f(int),那么y将有类型int (*)(int).也就是说,auto 执行函数指针转换.[2]
  • 最后,如果x有类型int&int&&,则y会有类型int.也就是说,auto 删除引用.

[1]您无法decltype在此使用,因为您无法复制初始化数组.

[2]您无法decltype在此使用,因为您无法初始化函数.

[3] auto条带引用的原因是C++没有引用类型的表达式!初始化后,引用的"引用"将变为不可见.

注意,decltype当它的参数不是id-expression时,它也会做一些完全不同的事情,我不会在这里讨论.


Seb*_*ann 7

每当您的变量类型与正在评估的表达式无关时.

例如:

struct Bar
{
    Bar(int) {} // implicitly constructable
}

struct Bar2
{
    Bar2(int) {} // implicitly constructable
}

struct Foo
{
    static Bar var;
}

struct Foo2
{
    static Bar2 var;
}

template <typename T>
void dummy()
{
    decltype(T::var) myVar = 42;
}

dummy<Foo>(); // myVar is of type Bar1
dummy<Foo2>(); // myVar is of type Bar2
auto myAutoVar = 42; // type is int
Run Code Online (Sandbox Code Playgroud)

当然这只是一个用例,还有更多的用例.


aar*_*man 7

decltype它的用途非常广泛,auto并且可以用来代替它.因此,我认为可以非常安全地说,decltype只应在完全必要的情况下使用,因此如果auto产生错误的结果,则应使用decltype.此外,您还不能使用auto返回类型和参数,因此您也可以decltype在那里使用.C++ 14将显着增加其潜在用途,auto我猜想c ++ 17将会更进一步.因此,decltype只有在需要更改结果类型时才会使用的情况expr

另一件需要考虑的事情是,decltype除非你正在编写库代码,否则不是必需的,如果你想让你的代码更简洁,那么auto对于日常编程auto来说很好,它可以用尽可能多的方式进行辩论,但它是在处理像lambdas这样的不可言说的类型时几乎是必要的.