我可以在非 void 返回函数上使用 [[noreturn]] 吗?
Can I use [[noreturn]] on non-void returning functions?
我以前从未见过 [[ noreturn ]] 用于非空 returning 函数。
下面的定义好吗?
[[ noreturn ]] int function();
int function(){
while(true){/* impl */}
return 0;
}
return 类型必须是 int
的原因是因为该函数是通过函数指针传递给另一个函数的。
所以假设来电者看起来像这样:
//call the non-returning function
int var = (*fptr)();
//use var some way (even though the function will never actually return)
std::cout << var;
这会表现出任何类型的未定义行为吗?
[[noreturn]]
的标准规范在 [dcl.attr.noreturn] 中。整个规范文本如下:
The attribute-token noreturn
specifies that a function does not return. It shall appear at most once in
each attribute-list and no attribute-argument-clause shall be present. The attribute may be applied to
the declarator-id in a function declaration. The first declaration of a function shall specify the noreturn
attribute if any declaration of that function specifies the noreturn
attribute. If a function is declared with
the noreturn
attribute in one translation unit and the same function is declared without the noreturn
attribute in another translation unit, the program is ill-formed; no diagnostic required.
If a function f
is called where f
was previously declared with the noreturn
attribute and f
eventually returns,
the behavior is undefined.
return类型没有提及。唯一重要的是函数不是 return。如果函数 returns(无论是 void
或 int
或 vector<vector<double>>
),则行为未定义。如果函数不 return,return 类型无关紧要。
来自 C++ 标准 §7.6.8/p2 Noreturn 属性 [dcl.attr.noreturn](Emphasis Mine):
If a function f is called where f was previously declared with the
noreturn attribute and f eventually returns, the behavior is
undefined. [ Note: The function may terminate by throwing an
exception. — end note ] [ Note: Implementations are encouraged to
issue a warning if a function marked [[noreturn]] might return. — end
note ]
因为你的函数永远不会达到 return 0;
所以没有 UB。
我发现了一个非 void [[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
而不是 [[noreturn]] T
)。
我以前从未见过 [[ noreturn ]] 用于非空 returning 函数。
下面的定义好吗?
[[ noreturn ]] int function();
int function(){
while(true){/* impl */}
return 0;
}
return 类型必须是 int
的原因是因为该函数是通过函数指针传递给另一个函数的。
所以假设来电者看起来像这样:
//call the non-returning function
int var = (*fptr)();
//use var some way (even though the function will never actually return)
std::cout << var;
这会表现出任何类型的未定义行为吗?
[[noreturn]]
的标准规范在 [dcl.attr.noreturn] 中。整个规范文本如下:
The attribute-token
noreturn
specifies that a function does not return. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. The attribute may be applied to the declarator-id in a function declaration. The first declaration of a function shall specify thenoreturn
attribute if any declaration of that function specifies thenoreturn
attribute. If a function is declared with thenoreturn
attribute in one translation unit and the same function is declared without thenoreturn
attribute in another translation unit, the program is ill-formed; no diagnostic required.If a function
f
is called wheref
was previously declared with thenoreturn
attribute andf
eventually returns, the behavior is undefined.
return类型没有提及。唯一重要的是函数不是 return。如果函数 returns(无论是 void
或 int
或 vector<vector<double>>
),则行为未定义。如果函数不 return,return 类型无关紧要。
来自 C++ 标准 §7.6.8/p2 Noreturn 属性 [dcl.attr.noreturn](Emphasis Mine):
If a function f is called where f was previously declared with the noreturn attribute and f eventually returns, the behavior is undefined. [ Note: The function may terminate by throwing an exception. — end note ] [ Note: Implementations are encouraged to issue a warning if a function marked [[noreturn]] might return. — end note ]
因为你的函数永远不会达到 return 0;
所以没有 UB。
我发现了一个非 void [[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
而不是 [[noreturn]] T
)。