Quantcast
Viewing all articles
Browse latest Browse all 22044

Strange behavior of noexcept operator in C++14

I found a strange behavior of the noexcept operator in C++14. The following code compiles well by both gcc and clang (with --std=c++14 option).

// test.cpp
#include <iostream>
#include <type_traits>

#if 1
#define TESTREF(X) X&&
#else
#define TESTREF(X) X const&
#endif

template <class F, class... Args>
struct is_noexcept_callable
    : public std::conditional_t<noexcept(std::declval<F>()(std::declval<Args>()...)), std::true_type, std::false_type> {};

template <
    class F,
    std::enable_if_t<is_noexcept_callable<F,int>::value,int> = 0
    >
int evalInt(int x, TESTREF(F) f) noexcept
{
    return static_cast<int>(f(x));
}

template <
    class F,
    std::enable_if_t<!is_noexcept_callable<F,int>::value,int> = 0
    >
int evalInt(int x, TESTREF(F) f)
{
    return static_cast<int>(f(x));
}

int id(int x) noexcept { return x; }
int thrower(int x) { throw(0); }

int main(int argc, char* argv[])
{
    std::cout << std::boolalpha
              << noexcept(evalInt(1,id))
              << std::endl;
    std::cout << std::boolalpha
              << is_noexcept_callable<decltype(thrower), int>::value
              << std::endl;
}

Executing the result program, I however got different results depending on compilers:

$ g++ --std=c++14 test.cpp
$ ./a.out
true
false
$ clang++ --std=c++14 test.cpp
$ ./a.out
false
false

I am not sure which is correct according to the standard.

More strangely, if I change the 5th line in the code above to #if 0 then gcc compiles the code into another differnt program:

$ ./a.out
true
true

As you see, the second value is changed. However, it depends only on the noexcept specification of thrower function that the macro doesn't touch. Is there any reasonable explanation to this, or is it just a bug?


Viewing all articles
Browse latest Browse all 22044

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>