Does an expression in noexcept
specifier's parentheses participate in SFINAE during overload resolution of function templates?
I want to make an wrapper for aggregates and want the std::is_constructible
predicate to work properly for it:
template< typename type >
struct embrace
: type
{
template< typename ...arguments >
embrace(arguments &&... _arguments) noexcept(noexcept(type{std::forward< arguments >(_arguments)...}))
: type{std::forward< arguments >(_arguments)...} // braces
{ ; }
};
int
main()
{
struct S { int i; double j; }; // aggregate
using E = embrace< S >;
E b(1, 1.0); // "parentheses"-constructible => can be used as usual types
b.i = 1; b.j = 2.0; // accessible
static_assert(std::is_constructible< E, int, double >{});
static_assert(std::is_constructible< E, struct B >{}); // want hard error here
return EXIT_SUCCESS;
}
But my attempt to use noexcept
operator inside noexcept
specification to enable SFINAE is failed, and the templated constructor accepts everything passed to it. How can the constructor be restricted?
It is not permitted by the Standard to specialize any predicates from <type_traits>
. How to deal with c-tors that accepts variadic template parameter packs and SFINAE in general? Is there an impasse and inherent language flaw?
It doesn't participate in template deduction because the
noexcept
specifier is not part of a function's type.Source
Therefore, when your template parameter
type
is deduced,noexcept
is not part of the deduced type. Your compiler seems to returntrue
for any type which is why you aren't able to detect whether it isnoexcept
or not; that is why everything is accepted.I ran into the same issue. You can check my question/answer here:
How can I detect whether a template argument is a noexcept function?
Basically, your only option is to wait for a C++17 compliant compiler.
SFINAE simply doesn't apply to exception-specifications, whether or not
noexcept
is part of the function type.See the note in [temp.deduct]/7:
P0012R1 didn't change anything in this respect.
Piotr's answer covers the fix for your code.
DEMO
(or shorter):
DEMO 2