c++ remove noexcept from decltype returned type
Asked Answered
A

2

14
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>


std::function<decltype(::bind)> mockbind = ::bind;

int main()
{
}

The code above works on most of the platforms I compile on. But on ubuntu 14.04 using g++-7 I get an error:

X.cpp:7:65: error: variable ‘std::function<int(int, const sockaddr*, unsigned int) noexcept> mockbind’ has initializer but incomplete type
 std::function<int(int, const sockaddr*, unsigned int) noexcept> mockbind = ::bind;
                                                                 ^~~~~~~~

Now if I manually go and change the type of mockbind

std::function<int(int, const sockaddr*, unsigned int) noexcept> mockbind = ::bind;

As expected I get the same error:
Now if I remove the noexcept

std::function<int(int, const sockaddr*, unsigned int)> mockbind = ::bind;

It compiles as expected.

So the question is can I apply some template code to remove the noexcept from the type returned by decltype and make it work as expected.

Ariel answered 30/8, 2017 at 16:24 Comment(2)
Doesn't auto mockbind = ::bind do what you want?Schindler
@whoan: No because it does not create a std::function<> type object. Without which it would be hard to bind funcotors to mockbind.Ariel
T
15

A simple class specialization trick should work:

template <typename T> struct remove_noexcept
{
    using type = T;
};
template <typename R, typename ...P> struct remove_noexcept<R(P...) noexcept>
{
    using type = R(P...);
};
template <typename T> using remove_noexcept_t = typename remove_noexcept<T>::type;

// ...

std::function<remove_noexcept_t<decltype(::bind)>> mockbind = ::bind;

You could somewhat easily extend it to remove noexcept from [member] function pointers, that's left as an excercise to the reader.

Also you could comment out using type = T; if you wish to get a compile-time error if there is no noexcept instead of leaving the type unchanged.

Turnsole answered 30/8, 2017 at 16:29 Comment(5)
I assume this also works adding specialisations for member functions as wellCornwallis
@Cornwallis Yes, it should. I decided to not bother for the sake of simplicity.Turnsole
Looks. Good. I'll test it tonight when I get homeAriel
@LokiAstari You're welcome, and you just gave me silver c++ badge. :PTurnsole
Works nearly everywhere Mac/Win/Linux. But is now failing on Ubuntu. Only took 7 years before it fails.Ariel
B
3

While HolyBlackCat's answer covers the majority of actual use cases, it would fail to cover many possible cases, including a qualified function type (e.g., int(int) const noexcept), a variadic templated variadic function (e.g., template<typename... Ts> void foo(Ts..., ...) noexcept), and pointer to member functions (which don't operate under normal pointer rules at all, e.g., int(foo::*)(int) noexcept).

Implementing a remove_noexcept trait that covers all of these edge cases is no small undertaking, but here's my take on it. I implemented remove_noexcept_t in terms of make_noexcept_t<T, bool>, whose second parameter allows you to toggle the resultant noexcept state (noexcept(true) or noexcept(false), as you'd expect).

Notably, this does work with pointer to member functions, but does not work with function pointers. This is by design (primarily following the logic of std::is_pointer), though you could fairly easily set up a using declaration like add_pointer_t<make_noexcept_t<remove_pointer_t<decay_t<T>>>>.

Live Demo (UPDATED 13 Oct 2022 - Added explicit licensing)

EDIT: The below implementation was not tested for accuracy with MSVC++ 2019 (v142) before I posted this. While it does work with GCC and Clang, this implementation does NOT work with MSVC++ 2019 (v142). The live demo link has been updated to a much longer implementation (twice as many specializations), which is too long to post to StackOverflow. That implementation has been tested with GCC, Clang, and MSVC++ 2019 (v142).

template<typename T, bool noexcept_state = true>
struct make_noexcept { using type = T; };

template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) noexcept, noexcept_state> { using type = R(Args...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const noexcept, noexcept_state> { using type = R(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile noexcept, noexcept_state> { using type = R(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile noexcept, noexcept_state> { using type = R(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) noexcept, noexcept_state> { using type = R(Args..., ...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const noexcept, noexcept_state> { using type = R(Args..., ...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile noexcept, noexcept_state> { using type = R(Args..., ...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile noexcept, noexcept_state> { using type = R(Args..., ...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) & noexcept, noexcept_state> { using type = R(Args...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const & noexcept, noexcept_state> { using type = R(Args...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile & noexcept, noexcept_state> { using type = R(Args...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile & noexcept, noexcept_state> { using type = R(Args...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) & noexcept, noexcept_state> { using type = R(Args..., ...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const & noexcept, noexcept_state> { using type = R(Args..., ...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile & noexcept, noexcept_state> { using type = R(Args..., ...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile & noexcept, noexcept_state> { using type = R(Args..., ...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) && noexcept, noexcept_state> { using type = R(Args...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const && noexcept, noexcept_state> { using type = R(Args...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile && noexcept, noexcept_state> { using type = R(Args...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile && noexcept, noexcept_state> { using type = R(Args...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) && noexcept, noexcept_state> { using type = R(Args..., ...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const && noexcept, noexcept_state> { using type = R(Args..., ...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile && noexcept, noexcept_state> { using type = R(Args..., ...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile && noexcept, noexcept_state> { using type = R(Args..., ...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) noexcept, noexcept_state> { using type = R(C::*)(Args...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const noexcept, noexcept_state> { using type = R(C::*)(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile noexcept, noexcept_state> { using type = R(C::*)(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile noexcept, noexcept_state> { using type = R(C::*)(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const noexcept, noexcept_state> { using type = R(C::*)(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile noexcept, noexcept_state> { using type = R(C::*)(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile noexcept, noexcept_state> { using type = R(C::*)(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) & noexcept, noexcept_state> { using type = R(C::*)(Args...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const & noexcept, noexcept_state> { using type = R(C::*)(Args...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile & noexcept, noexcept_state> { using type = R(C::*)(Args...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile & noexcept, noexcept_state> { using type = R(C::*)(Args...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) & noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const & noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile & noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile & noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) && noexcept, noexcept_state> { using type = R(C::*)(Args...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const && noexcept, noexcept_state> { using type = R(C::*)(Args...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile && noexcept, noexcept_state> { using type = R(C::*)(Args...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile && noexcept, noexcept_state> { using type = R(C::*)(Args...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) && noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const && noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile && noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile && noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) const volatile && noexcept(noexcept_state); };

// MSVC++ 2019 (v142) doesn't allow `noexcept(x)` with a template parameter `x` in the template specialization list.
// (e.g., `struct make_noexcept<R(Args...) noexcept(noexcept_state)>` gives - C2057: expected constant expression)
// GCC 7.1.0 and Clang 5.0.0 (and later versions) were tested and do allow this, so MSVC++ is probably wrong.
// $ g++ prog.cc -Wall -Wextra -std=c++17 -pedantic
// $ clang++ prog.cc -Wall -Wextra -std=c++17 -pedantic

template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...), noexcept_state> { using type = R(Args...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const, noexcept_state> { using type = R(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile, noexcept_state> { using type = R(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile, noexcept_state> { using type = R(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...), noexcept_state> { using type = R(Args..., ...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const, noexcept_state> { using type = R(Args..., ...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile, noexcept_state> { using type = R(Args..., ...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile, noexcept_state> { using type = R(Args..., ...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...)&, noexcept_state> { using type = R(Args...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const &, noexcept_state> { using type = R(Args...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile &, noexcept_state> { using type = R(Args...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile &, noexcept_state> { using type = R(Args...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...)&, noexcept_state> { using type = R(Args..., ...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const &, noexcept_state> { using type = R(Args..., ...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile &, noexcept_state> { using type = R(Args..., ...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile &, noexcept_state> { using type = R(Args..., ...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) &&, noexcept_state> { using type = R(Args...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const &&, noexcept_state> { using type = R(Args...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile &&, noexcept_state> { using type = R(Args...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile &&, noexcept_state> { using type = R(Args...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) &&, noexcept_state> { using type = R(Args..., ...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const &&, noexcept_state> { using type = R(Args..., ...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile &&, noexcept_state> { using type = R(Args..., ...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile &&, noexcept_state> { using type = R(Args..., ...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...), noexcept_state> { using type = R(C::*)(Args...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const, noexcept_state> { using type = R(C::*)(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile, noexcept_state> { using type = R(C::*)(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile, noexcept_state> { using type = R(C::*)(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...), noexcept_state> { using type = R(C::*)(Args..., ...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const, noexcept_state> { using type = R(C::*)(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile, noexcept_state> { using type = R(C::*)(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile, noexcept_state> { using type = R(C::*)(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...)&, noexcept_state> { using type = R(C::*)(Args...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const &, noexcept_state> { using type = R(C::*)(Args...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile &, noexcept_state> { using type = R(C::*)(Args...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile &, noexcept_state> { using type = R(C::*)(Args...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...)&, noexcept_state> { using type = R(C::*)(Args..., ...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const &, noexcept_state> { using type = R(C::*)(Args..., ...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile &, noexcept_state> { using type = R(C::*)(Args..., ...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile &, noexcept_state> { using type = R(C::*)(Args..., ...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) &&, noexcept_state> { using type = R(C::*)(Args...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const &&, noexcept_state> { using type = R(C::*)(Args...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile &&, noexcept_state> { using type = R(C::*)(Args...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile &&, noexcept_state> { using type = R(C::*)(Args...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) &&, noexcept_state> { using type = R(C::*)(Args..., ...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const &&, noexcept_state> { using type = R(C::*)(Args..., ...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile &&, noexcept_state> { using type = R(C::*)(Args..., ...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile &&, noexcept_state> { using type = R(C::*)(Args..., ...) const volatile && noexcept(noexcept_state); };

template<typename T, bool noexcept_state = true>
using make_noexcept_t = typename make_noexcept<T, noexcept_state>::type;

template<typename T>
using remove_noexcept_t = make_noexcept_t<T, false>;
Brader answered 16/4, 2019 at 5:51 Comment(5)
Additionally, this could be used as a basis for an is_noexcept trait by checking is_same_v<T, make_no_except_t<T>>.Brader
I tested compilation of this with MSVC++ 2019 (v142), but all of the type check tests were done on Wandbox (GCC and Clang). MSVC++ completely discards noexcept(noexcept_state) in every case.Brader
Thanks for undertaking that tedious task ... saved me a lot of workMicroeconomics
It was brought to my attention that SO contributions are implicitly licensed under CC BY-SA 4.0. I updated the live demo link to explicitly include the WTFPL. Attribution is appreciated, but not required.Brader
Agreed, it is rather an uncommon situation for the use of Stackoverflow, insofar you are publishing complete code here (which is very much appreciated)Microeconomics

© 2022 - 2024 — McMap. All rights reserved.