SFINAE and noexcept specifier

北战南征 提交于 2019-12-04 03:04:45

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:

The substitution occurs in all types and expressions that are used in the function type and in template parameter declarations. The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions. The substitution proceeds in lexical order and stops when a condition that causes deduction to fail is encountered. [ Note: The equivalent substitution in exception specifications is done only when the exception-specification is instantiated, at which point a program is ill-formed if the substitution results in an invalid type or expression. —end note ]

P0012R1 didn't change anything in this respect.

Piotr's answer covers the fix for your code.

Piotr Skotnicki

How can the constructor be restricted?

#include <utility>

template <typename type>
struct embrace : type
{
    template <typename... arguments
            , typename = decltype(type{std::declval<arguments>()...})>
    embrace(arguments&&... _arguments)
        noexcept(noexcept(type{std::forward<arguments>(_arguments)...}))
        : type{std::forward<arguments>(_arguments)...}
    {
    }
};

DEMO

(or shorter):

#include <utility>

template <typename type>
struct embrace : type
{
    template <typename... arguments
            , bool NoExcept = noexcept(type{std::declval<arguments>()...})>
    constexpr
    embrace(arguments&&... _arguments)
        noexcept(NoExcept)
        : type{std::forward<arguments>(_arguments)...}
    {
    }
};

DEMO 2

user2296177

Does an expression in noexcept specifier's parentheses participate in SFINAE during overload resolution of function templates?

It doesn't participate in template deduction because the noexcept specifier is not part of a function's type.

The noexcept-specification is not a part of the function type. (until C++17)

Source

Therefore, when your template parameter type is deduced, noexcept is not part of the deduced type. Your compiler seems to return true for any type which is why you aren't able to detect whether it is noexcept 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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!