Please see the following code:
#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};
}
This code seems to be accepted by GCC/Clang, but MSVC 2017 rejects it. It seems that MSVC compiler tries to compute the noexcept specifier before understanding that #1 is not an appropriate overload (due to incompatibility between tag
and int
) so should be discarded. Thus it tries to evaluate is_noexcept<int>::value
and finds out noexcept(A{std::declval<int>()})
is ill-formed. Since this happens not in the immediate context , this is not where SFINAE comes in, so hard error.
(In fact, I'm not pretty sure about this, but I've confirmed that if I put noexcept(A{std::declval<Args>()...})
instead of is_noexcept<Args...>::value
at /*Here*/
to make the failure inside the immediate context, the MSVC compiler happily drops #1 and calls #2. Is this right?)
I suspect GCC/Clang is right and MSVC is wrong, but which one is correct?
Aucun commentaire:
Enregistrer un commentaire