c++ - `decltype(auto)` 变量是否有任何实际用例?

标签 c++ c++14 auto type-deduction decltype-auto

根据我的个人经验和对 What are some uses of decltype(auto)? 等问题的咨询答案我可以为 decltype(auto) 作为 函数返回类型占位符找到很多有值(value)的用例。

但是,我很难为 decltype(auto) 变量考虑任何有效的(即有用的、现实的、有值(value)的)用例。想到的唯一可能性是存储返回 decltype(auto) 的函数的结果以供以后传播,但 auto&& 也可以在那里使用,它会是更简单。

我什至搜索了我所有的项目和实验,发现 391 次出现的 decltype(auto) 都是返回类型占位符。

那么,decltype(auto) 变量是否有任何实际的用例?或者这个功能只有在用作返回类型占位符时才有用?


How do you define "realistic"?

我正在寻找一个提供值(value)的用例(即它不仅仅是一个展示该功能如何工作的示例)其中 decltype(auto) 是完美的选择,与诸如 auto&& 之类的替代方法或根本不声明变量相比。

问题域无关紧要,它可能是一些晦涩的元编程极端案例或神秘的函数式编程结构。然而,这个例子需要让我去“嘿,这很聪明/漂亮!”并且使用任何其他功能来达到相同的效果需要更多样板或有某种缺点。

最佳答案

本质上,变量的情况与函数的情况相同。这个想法是我们用 decltype(auto) 变量存储函数调用的结果:

decltype(auto) result = /* function invocation */;

那么,result就是

  • 如果结果是纯右值,则为非引用类型,

  • 如果结果是左值,则为(可能是 cv 限定的)左值引用类型,或者

  • 如果结果是 xvalue,则为右值引用类型。

现在我们需要一个新版本的 forward 来区分 prvalue 情况和 xvalue 情况:(避免使用名称 forward 以防止 ADL 问题)

template <typename T>
T my_forward(std::remove_reference_t<T>& arg)
{
    return std::forward<T>(arg);
}

然后使用

my_forward<decltype(result)>(result)

std::forward不同,该函数用于转发decltype(auto)变量。所以它不是无条件返回引用类型,应该是用decltype(variable)调用的,可以是T,T&T&&,以便它可以区分左值、xvalue 和纯右值。因此,如果 result

  • 非引用类型,然后用非引用T调用第二个重载,返回非引用类型,产生prvalue;

  • 一个左值引用类型,然后第一个重载调用一个T&,返回T&,得到一个左值;

  • 一个右值引用类型,然后用T&&调用第二个重载,返回T&&,得到一个xvalue。

这是一个例子。考虑到您想要包装 std::invoke 并将某些内容打印到日志中:(示例仅用于说明)

template <typename F, typename... Args>
decltype(auto) my_invoke(F&& f, Args&&... args)
{
    decltype(auto) result = std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
    my_log("invoke", result); // for illustration only
    return my_forward<decltype(result)>(result);
}

现在,如果调用表达式是

  • 一个prvalue,则result为非引用类型,函数返回非引用类型;

  • 一个非常量左值,那么result就是一个非常量左值引用,函数返回一个非常量左值引用类型;

  • 一个const左值,那么result就是一个const左值引用,函数返回一个const左值引用类型;

  • 一个xvalue,那么result就是一个右值引用类型,函数返回一个右值引用类型。

给定以下函数:

int f();
int& g();
const int& h();
int&& i();

以下断言成立:

static_assert(std::is_same_v<decltype(my_invoke(f)), int>);
static_assert(std::is_same_v<decltype(my_invoke(g)), int&>);
static_assert(std::is_same_v<decltype(my_invoke(h)), const int&>);
static_assert(std::is_same_v<decltype(my_invoke(i)), int&&>);

( live demo , move only test case )

如果使用 auto&& 代替,代码将难以区分纯右值和 xvalue。

关于c++ - `decltype(auto)` 变量是否有任何实际用例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57438217/

相关文章:

c++ - 序列点从何而来?

c++ - 自动推导可以隐式添加常量吗?

c++ - 强制 auto 成为循环范围内的引用类型

c++ - 不匹配 operator= 使用 std::vector

c++ - 编译一个静态二进制文件,其中代码有一个函数 gethostbyname

c++ - 在 txt 文件中查找最小和最大数字

c++ - 包含 std::queue 的类的值初始化

c++ - 在模板参数中通过 SFINAE 选择构造函数

c++ - 在循环中使用自动 C++

C++ 运算符重载和参数化构造函数