c++ 什么是void()纯右值,如何使用?

jobtbby3  于 2023-08-09  发布在  其他
关注(0)|答案(2)|浏览(99)

在阅读cppreference对functional style cast的描述时,我偶然发现了以下对void()的解释:
如果target-type是(可能是cv限定的)void,则表达式是没有结果对象的void纯右值(C++17起)
现在我明白了,我可以像这样创建一个void()纯右值,但是我可以用它来做什么,为什么这是可能的呢?

n1bvdmb6

n1bvdmb61#

我想你是指这一段
1.函式样式的转型运算式是由简单型别规范或typedef规范(换句话说,单字型别名称,也就是unsigned int(expression)int*(expression)这类的情况无效),后面接着括号中以逗号分隔的运算式清单所组成。
而子弹

  • 如果括号中没有表达式:如果target-type命名了一个非数组的完整对象类型,则此表达式是target-type类型的主值,指定了一个临时的(C17之前),其结果对象(可能添加了cv限定符)(C17之后)是该类型。如果target-type是对象型别,则对象会以值初始化。如果target-type是(可能是cv限定的)void,则表达式是没有结果对象的void prvalue(自C++17起)。

如果你把标准的语言放在一边,它实际上并没有那么复杂。我想你会奇怪为什么有人会写这样的东西:

void bar() {
    return void();
}

字符串
根据上述,这是有效的,但不是真正有用的。“现在,假设您有一个如下所示的函数模板:

template <typename T>
auto foo() {
    return typename T::value_type();
}


然后,您可以使用T示例化它,其中value_typevoid

struct X{
    using value_type = void;
};
int main() {
    foo<X>();
}


没有返回对象,但foo<X>中表达式T::value_type的类型为void,函数有void返回类型。

wgxvkvu9

wgxvkvu92#

但我能用它做什么
有几个地方它是有用的,直接使用:

  • SFINAE与decltype(在C++20中用requires作为超级种子)
template <typename T>
auto print_foo(const T& value)
-> decltype(foo(t), void()) // SFINAE on foo(t), but return void
{
    std::cout << foo(t);
}

字符串

  • 拆分表达式来处理邪恶的operator,(如果一方是void,则没有自定义可用的operator,可用)。
template <Typename F, typename...Ts>
void for_each_call(F f, const Ts&... args)
{
    ((f(args), void()), ...);
}


在泛型代码中也有替换后:

template <typename T>
T foo()
{
    return T();
}


foo<void>()有效。

相关问题