我之前从未见过使用非空返回函数的[[ noreturn ]]。
以下是否定义明确?
[[ noreturn ]] int function();
int function(){
while(true){/* impl */}
return 0;
}
返回类型必须为int
的原因是因为函数通过函数指针传递给另一个函数。
所以假设调用者看起来像这样:
//call the non-returning function
int var = (*fptr)();
//use var some way (even though the function will never actually return)
std::cout << var;
这会表现出任何未定义的行为吗?
答案 0 :(得分:24)
[[noreturn]]
上的标准规范在[dcl.attr.noreturn]中。整个规范性文本如下:
attribute-token
noreturn
指定函数不返回。它最多只能出现一次 每个属性列表并且不存在 attribute-argument-clause 。该属性可以应用于 函数声明中的 declarator-id 。函数的第一个声明应指定noreturn
如果该函数的任何声明指定noreturn
属性,则为attribute。如果声明了一个函数 一个翻译单元中的noreturn
属性和相同的函数在没有noreturn
的情况下声明 属于另一个翻译单元,该程序是不正确的;无需诊断。如果调用函数
f
,之前使用f
属性声明了noreturn
,并且f
最终返回, 行为未定义。
没有提及返回类型。唯一重要的是功能不归。如果函数返回(void
或int
或vector<vector<double>>
),则行为未定义。如果函数没有返回,则返回类型并不重要。
答案 1 :(得分:10)
来自C ++标准§7.6.8/ p2 Noreturn属性[dcl.attr.noreturn]( Emphasis Mine ):
如果调用函数f,其中f先前已使用 noreturn属性和f最终返回,行为是 undefined。 [注意:该函数可以通过抛出一个函数来终止 例外。 - 尾注] [注:鼓励实施 如果标记为[[noreturn]]的函数可能返回,则发出警告。 - 结束 注意]
由于您的功能永远不会到达return 0;
,因此没有UB。
答案 2 :(得分:0)
我发现了一个非空函数 docker volume rm
的实际例子。在一种情况下,当在 [[noreturn]]
运算符中使用时提供正确的 ?:
运算符结果类型:
?:
注意:人们可能会觉得 template <class T> [[noreturn]] T fail(char const *s) noexcept { puts(s); exit(1); }
enum E { V1, V2 };
int f(E e) {
return (e == V1) ? 1 : (e == V2) ? 2 : fail<E>("bad e");
}
运算符中的 [[noreturn]]
函数在计算 ?:
结果类型时可能会被忽略。但这是不可能的,因为 ?:
不是表达式结果类型的一部分([[noreturn]]
具有结果类型 fail<T>("")
而不是 T
)。