Jun*_*eon 9 c++ language-lawyer noexcept c++11
请参阅以下代码:
#include <utility>
struct A {
A(int, int) {}
};
struct tag {};
template <class... Args>
struct is_noexcept {
static constexpr bool value = noexcept(A{std::declval<Args>()...});
};
struct B : A {
//#1
template <class... Args>
B(tag, Args&&... args) noexcept(/*Here*/is_noexcept<Args...>::value) :
A{std::forward<Args>(args)...} {}
//#2
B(int x, int y) : A{x, y} {}
};
int main()
{
B x{0, 0};
}
Run Code Online (Sandbox Code Playgroud)
这段代码似乎被GCC/Clang接受,但MSVC 2017拒绝接受.似乎MSVC编译器试图理解是#1不是适当的过载(由于之间的不相容之前计算noexcept符tag和int),因此应被丢弃.因此,它试图评估is_noexcept<int>::value并发现noexcept(A{std::declval<int>()})是不正确的.由于这不是在紧急情况下发生的,因此这不是SFINAE的用武之地,所以很难发生错误.
(其实,我不是很肯定这一点,但我已经证实,如果我把noexcept(A{std::declval<Args>()...}),而不是is_noexcept<Args...>::value在/*Here*/做直接的上下文中发生故障时,MSVC编译器愉快地下降#1和#调用2.这是正确的? )
我怀疑GCC/Clang是对的,MSVC是错的,但哪一个是正确的?
这是一个MSVC错误.作为CWG 1330的结果,[except.spec]/13中的规则是:
在以下情况下,需要考虑异常规范:
- 在表达式中,该函数是唯一的查找结果或一组重载函数的选定成员([basic.lookup],[over.match],[over.over]);
- 该函数是odr-used,或者,如果它出现在未评估的操作数中,如果表达式被潜在评估,则会使用该函数;
- 将异常规范与另一个声明的规范进行比较(例如,显式特化或覆盖虚函数);
- 功能定义; 要么
- 调用该函数的默认特殊成员函数需要异常规范.[注意:默认声明不需要评估基本成员函数的异常规范,直到需要派生函数的隐式异常规范,但显式noexcept-specifier需要隐式异常规范进行比较. - 结束说明]
仅在需要时如上所述评估默认特殊成员函数的异常规范; 类似地,仅在需要时实例化函数模板的特化或类模板的成员函数的noexcept-specifier.
B(tag, Args&&...)不需要异常规范(我们不满足任何这些项目符号),因此不应该实例化它.
另请注意,异常规范中的替换失败不是直接上下文的一部分,并且不会是SFINAE友好的错误.
| 归档时间: |
|
| 查看次数: |
196 次 |
| 最近记录: |