I have tried to understand a bit more how does the noexcept operator works and how it can be used in template. My goal was to enable or disable a template function, depending on the noexcept type of one the member function class.
class ObjTestNoExcept
{
public:
ObjTestNoExcept() noexcept {}
void Test() noexcept {}
};
class ObjTestExcept
{
public:
ObjTestExcept() {}
void Test() {}
};
template <class T, typename = typename std::enable_if_t<noexcept(T().Test()), T>>
void DoSomething()
{
std::cout << "OK" << std::endl;
}
int main()
{
DoSomething<ObjTestNoExcept>();
DoSomething<ObjTestExcept>(); // error C2672: 'DoSomething': no matching overloaded function found
return 0;
}
It works as expected for the ObjTextExcept class and disables the function, and it works as expected for the ObjTestNoExcept class and enables the function.
However, if I remove the noexcept keyword on the ObjTestNoExcept class then the function is disabled whereas it's still noexcept.
class ObjTestNoExcept
{
public:
ObjTestNoExcept() {}
void Test() noexcept {}
};
template <class T, typename = typename std::enable_if_t<noexcept(T().Test()), T>>
void DoSomething()
{
std::cout << "OK" << std::endl;
}
int main()
{
DoSomething<ObjTestNoExcept>(); // error C2672: 'DoSomething': no matching overloaded function found
return 0;
}
I can not figure out what is wrong with the removal of the noexcept keyword on the constructor.
This code has been developed under Visual Studio 2017 Professional Version 15.6.3.
Thanks for reading.
Olivier
noexcept(X)
is true, if the expression X
is noexcept. In the second example (noexcept(T().Test())
), two things are mixed: the construction of T
, then the call to the Test
method. That's why the removal of the noexcept from the constructor breaks the code.
To avoid assuming a noexcept default constructor, use: noexcept(std::declval<T>().Test())