Search code examples
c++c++11g++c++14gcc7

How does `std::mem_fn` detect noexceptness in gcc 7.1.0


With gcc 7.1.0 std::mem_fn is able to detect noexcept-ness on a member function pointer. How does it do this? I thought the noexcept specifier was not a part of the function type?


What is even more confusing is when I remove the noexcept specifier on one method from https://wandbox.org/permlink/JUI3rsLjKRoPArAl all the noexcept values change as seen here https://wandbox.org/permlink/yBJ0R4PxzAXg09ef. And when one is noexcept, all are noexcept. How? Is this a bug?


Solution

  • The behaviour you're seeing with GCC in C++14 mode is a bug, see https://gcc.gnu.org/PR77369

    In the comments you ask:

    Also the declaration of mem_fn since c++17 does not have a noexcept overload, then how does it detect this information from the user?

    It doesn't need to have a noexcept overload, consider this C++17 code:

    template<typename T>
      constexpr bool is_noexcept_callable(T t) {
        return noexcept(t());
      }
    
    void f() noexcept { }
    void g() { }
    static_assert( is_noexcept_callable(f) );
    static_assert( !is_noexcept_callable(g) );
    

    There's no need to have a noexcept overload of is_noexcept_callable because in C++17 the exception-specification is part of the type, so all the information is already encoded in the type T. When you instantiate std::mem_fn with a pointer to a noexcept(true) function it knows that invoking that function can't throw. When you instantiate it with a noexcept(false) function it knows it might throw.

    Finally, the reason your example doesn't compile in C++17 mode with GCC 7.1 is https://gcc.gnu.org/PR80478 which is fixed in GCC 7.2 (so upgrade your compiler).