Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I detect whether a template argument is a noexcept function?

I have function to generate a lambda that acts as a wrapper to a function I can invoke later:

template <typename F, typename... FArgs>
auto make_lambda( F&& f, FArgs&&... f_args )
{
    return [&] () -> std::result_of_t<F( FArgs... )>
    {
        return std::forward<F>( f )( std::forward<FArgs>( f_args )... );
    };
}

I'd like to make the returned lambda noexcept when argument f is noexcept, so my function's return would look like this:

return [&] () noexcept( is_noexcept<decltype( f )>::value )
    -> std::result_of_t<F( FArgs... )>
{
    return std::forward<F>( f )( std::forward<FArgs>( f_args )... );
};

My attempt:

#include <type_traits>

void f() {}
void g() noexcept {}

template <typename F, typename... Args>
struct is_noexcept : std::false_type {};

template <typename F, typename... Args>
struct is_noexcept<F( Args... ) noexcept> : std::true_type {};

int main()
{
    bool constexpr func_test_a{ is_noexcept<decltype( f )>::value }; // true
    bool constexpr func_test_b{ is_noexcept<decltype( g )>::value }; // true
}

However, the test always returns true. What am I missing? Can anyone provide a solution to this problem?

like image 569
user2296177 Avatar asked Nov 08 '15 01:11

user2296177


People also ask

When to declare noexcept?

We recommended you apply noexcept to any function that never allows an exception to propagate up the call stack. When a function is declared noexcept , it enables the compiler to generate more efficient code in several different contexts. For more information, see Exception specifications.

Why do we use noexcept?

The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions. It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.


2 Answers

You can use the noexcept operator, which takes an expression and produces true if that expression is noexcept.

Untested, but this might work for your use case.

return [&] () noexcept(noexcept(std::forward<F>( f )( std::forward<FArgs>( f_args )... )))
    -> std::result_of_t<F( FArgs... )>
{
    return std::forward<F>( f )( std::forward<FArgs>( f_args )... );
};
like image 124
Jeremy Roman Avatar answered Sep 20 '22 05:09

Jeremy Roman


From: http://en.cppreference.com/w/cpp/language/noexcept_spec

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

Currently, template deduction will not produce the correct results since the noexcept specifier is not part of a function's type; template type deduction will not work until C++17. My way of detecting whether a function is noexcept will be valid in C++17 as will this answer's way.

like image 32
user2296177 Avatar answered Sep 19 '22 05:09

user2296177