【问题标题】:When should I use decltype(expression)?什么时候应该使用 decltype(expression)?
【发布时间】:2020-07-15 13:26:16
【问题描述】:

我理解为什么我们需要 decltype(auto) 并且它与 auto 不同,但我不知道为什么以及何时应该/需要使用 decltype(expression)。在cppreference 的所有示例中,我只能使用 decltype(auto),我检查了它。 提前感谢您的帮助。

【问题讨论】:

  • void foo(int i) { for (decltype(i) j = 0; j < i; ++j) ... }
  • @Evg 给出答案

标签: c++ decltype


【解决方案1】:

我能想到的最简单的例子是:

void foo(int i) {
    for (decltype(i) j = 0; j < i; ++j) 
        ...
}

这里,索引j 自动与上限i 具有相同的类型。

另一个示例由 lambda 表达式提供:

[](auto i) {
    for (decltype(i) j = 0; j < i; ++j) 
        ...    
}

【讨论】:

  • 如果你可以走回前面,那么你也可以这样做for(auto j = i; j--;)
  • 但我可以使用 decltype(auto) 而不是 decltype(i)
  • @DoehJohn 在这个特定的例子中,你可以。但这个想法是 int 可以是任何类型,可能像在通用 lambda 中一样未知。
  • @Evg 是的,但是 [](auto i) { for (decltype(auto) j = 0; j
  • @DoehJohn, j 将始终具有 int 类型,独立于 i 的类型。
【解决方案2】:

但我不知道为什么以及何时应该/需要使用decltype(expression)

在 C++11 中,您可以使用尾随返回类型,但不能使用自动推导的返回类型。例如:

template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) { return t + u; }

C++14 等价物是:

template<typename T, typename U>
decltype(auto) add(T t, U u) { return t + u; }

另一个用途是 SFINAE,例如检测是否存在具有特定名称的成员函数:

#include <iostream>

template<class T>
auto test_has_f(T* p) -> decltype(static_cast<void>(p->f()), std::true_type{}); // Cast to void to avoid user-defined operator,(), if any.

std::false_type test_has_f(void*);

template<class T>
using HasF = decltype(test_has_f(static_cast<T*>(0)));

struct A {};
struct B { void f(); };

int main() {
    std::cout << HasF<A>::value << '\n'; // Outputs 0.
    std::cout << HasF<B>::value << '\n'; // Outputs 1.
}

【讨论】:

  • 很遗憾,但我无法真正理解您的第二个代码示例在做什么.. 去阅读关于 SFINAE 的文章
  • @DoehJohn 在编译时检测一个类是否有一个名为f的成员函数,参见main中的2行用法。
  • 我了解用法,您编写了自己的特征,但不太了解它的幕后工作原理
【解决方案3】:

有时你需要声明一个与另一个类型相关但又想保持不可知的类型:

struct foo
{
    std::vector<int> data;
    decltype(data)::iterator it;
};

【讨论】:

  • 一个实际的 表达式 来推断?这里有一个类型。
  • @user253751 data 是一个表达式
  • @AsteroidsWithWings 你不能从中推断出一个
  • @user253751 啊,没看到第一个版本。 ?
猜你喜欢
  • 2023-04-02
  • 2011-04-15
  • 2017-04-10
  • 2012-03-19
  • 2018-05-12
  • 2018-12-11
  • 1970-01-01
  • 2022-09-28
  • 2021-09-07
相关资源
最近更新 更多