相关疑难解决方法(0)

无效{}是否合法?

这是这个问题的后续行动.
评价和在回答据说超过一次,更多的void{}没有一个有效的类型-ID,也不是一个有效的表达式.

这很好,它是有道理的,这就是全部.

然后我通过工作草案的[7.1.7.4.1/2](占位符类型扣除).
有人说:

[...]
- 对于使用return 包含占位符类型的返回类型声明的函数中发生的非丢弃  语句,  T 是声明的返回类型,并且  e 是return语句的操作数  .如果  return 语句没有操作数,那么  e 是  void{};
[...]

那么,void{}(概念上)合法与否?
如果它在工作草案中提到是可接受的(尽管只是作为- 如果它是一个 -陈述),它必须是合法的.这意味着它也decltype(void{})应该是有效的,作为一个例子.
否则,工作草案应该使用void()而不是void{}


嗯,说实话,我很确定我没有足够的技巧来指出工作草案中的错误,所以真正的问题是:我的推理出了什么问题?上面的子弹中提到了
什么void{},以及为什么在这种情况下它是一个法律表达?

c++ void language-lawyer return-type-deduction c++17

28
推荐指数
2
解决办法
673
查看次数

建造一个空洞类型?

我得到了一段void()用作参数的代码.代码不编译......很明显?

我们可以实例化任何类型的东西void吗?我相信答案是否定的,除了a void*.例如:

  1. 编写函数void askVoid(void param) {}错误:

参数可能没有void类型

  1. 编写函数void askNaught() {}并使用askNaught(void())`错误调用它:

错误C2660 :: takeNaught函数不带1个参数

  1. 编写模板化函数template <typename T> void takeGeneric(T param) {}并调用它有takeGeneric(void())错误:

错误C2893:无法专门化功能模板 void takeGeneric(T)

  1. 声明void voidType错误:

不允许使用不完整的类型

  1. 声明auto autoVoid = void()错误:

不能推断出auto类型

  1. 声明void* voidPtr工作正常,但remove_pointer_t<decltype(voidPtr)> decltypeVoid错误:

错误C2182 :: decltypeVoid非法使用类型void

就是这样,对吧?void()C++中没有地方可供选择吗?这只是我给出的错误代码,对吧?

c++ void

21
推荐指数
3
解决办法
2025
查看次数

如果void实际定义为`struct void {};`,那么现有的C++代码会破坏多少

void在C++类型系统中是一个奇怪的疣.这是一个不完整的类型,无法完成,它有各种有关限制方式的魔术规则:

类型cv void是不完整的类型,无法完成; 这种类型有一组空值.它用作不返回值的函数的返回类型.任何表达式都可以显式转换为cv void([expr.cast]).类型的表达式CV void应仅作为一个表达式语句,作为逗号表达式的操作数,作为一个第二或第三操作数?:([expr.cond]),作为操作数typeid,noexceptdecltype,如在表达return具有返回类型cv 的函数的语句void,或作为显式转换为cv 类型的操作数的语句void.

(N4778,[basic.fundamental]9)

除了对所有这些奇怪规则的痒感之外,由于它的使用方式有限,在编写模板时经常会出现一个痛苦的特殊情况; 通常情况下,我们希望它表现得更像std::monostate.


让我们想象一下,除了上面的引文,标准说的void是类似的东西

这是一个定义相当于以下类型的类型:

struct void {
    void()=default;
    template<typename T> explicit void(T &&) {}; // to allow cast to void
};
Run Code Online (Sandbox Code Playgroud)

保持void *魔法 - 可以别名任何对象,数据指针必须在往返过程中存活void *.

这个:

  • 应涵盖void"适当"类型的现有用例;
  • 可能允许删除关于它通过标准传播的相当数量的垃圾 - 例如[expr.cond]2可能是不需要的,[stmt.return]将大大简化(同时仍然保持"异常",return …

c++ language-design generic-programming void language-lawyer

20
推荐指数
1
解决办法
415
查看次数

如果条件可以为空

Nullable<T>像这样的语法糖有很多:

int? parsed to Nullable<int>

int? x = null
   if (x != null) // Parsed to if (x.HasValue)

x = 56; // Parsed to x.Value = 56;
Run Code Online (Sandbox Code Playgroud)

和更多.

为什么if使用Nullable条件不起作用?

if (x)
{} 
Run Code Online (Sandbox Code Playgroud)

它得到Complier错误,说无法转换Nullable<bool>bool.
为什么它没有被解析if (x.HasValue && x.Value == true)或类似的东西?

这是最明显的用法 Nullable<bool>

.net c# compiler-construction nullable

7
推荐指数
3
解决办法
5375
查看次数

构造一个空对象

由于出现错误,以下代码示例似乎使用 GCC 12.2 进行编译,与 Clang 15 和 MSVC 19.33 不同illegal initializer type 'void'。我预计代码会被所有三个编译器拒绝,因为构造(临时)void 对象没有意义。

auto f() { return void{}; }

using t = decltype(f());
Run Code Online (Sandbox Code Playgroud)

在示例中,函数f仅与未计算的操作数一起使用。f是否允许这样使用,或者甚至应该拒绝它的定义?(我知道void()创建纯右值的法律表达式,但这不属于本文的重点。)

标准中看似相关的段落:

[basic.types]/5

不完全定义的对象类型和 cv void 是不完整类型 ([basic.fundamental])。

[basic.types]/11.43

不完全定义的对象类型的实例的大小和布局是未知的。

c++ language-lawyer c++20

7
推荐指数
1
解决办法
243
查看次数

return 语句中临时 void 对象的值初始化

如果我没记错的话,允许return void()在函数模板中编写以避免不必要的专业化和void类型重载。

同时,return void{}Clang 不识别类似的语法:

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

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

int main() {
    // ok everywhere
    foo<void>();

    // error in Clang
    bar<void>();
}
Run Code Online (Sandbox Code Playgroud)

Clang 16 打印错误:

error: illegal initializer type 'void'
Run Code Online (Sandbox Code Playgroud)

在线演示: https: //gcc.godbolt.org/z/6o89reK3G

cppreference中,我没有找到答案:对于非聚合类型T(), 和T{}应该表现相同。并且没有关于void类型的特殊注释。

这只是一个 Clang bug,还是相反,它是唯一严格遵循标准的编译器?

c++ templates return void language-lawyer

6
推荐指数
1
解决办法
135
查看次数