【发布时间】:2019-01-01 05:25:03
【问题描述】:
请看以下代码:
#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};
}
此代码似乎被 GCC/Clang 接受,但 MSVC 2017 拒绝它。
似乎 MSVC 编译器在理解 #1 不是适当的重载(由于 tag 和 int 之间的不兼容)之前尝试计算 noexcept 说明符,因此应该丢弃。因此,它尝试评估 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 是错的,但哪一个是对的?
【问题讨论】:
-
我会说“像往常一样”。
标签: c++ c++11 language-lawyer noexcept