notaorb
notaorb

Reputation: 2180

How std::enable_if prevents declaration of member template?

Stroustrup C++ 4th Ed Page 796 states that

"If Enable_if’s condition evaluates to false, the whole function declaration of which it is part is completely ignored." and "...we don’t declare anything.".

I have also read this suggested thread in which SFINAE only works if substitution in argument deduction of a template argument makes the construct ill-formed.

For this example, I am trying to understand how SFINAE omits the Enable_if<false, T> f0(int x) {}; construct.

Is it because of the lack of a return type ::type makes the template construct ill-formed language-wise?

#include <type_traits>
using namespace std;

template<bool B, typename T>
using Enable_if = typename std::enable_if<B, T>::type;

struct X 
{
   template <class T>
   Enable_if<false, T> f0(int x) {};
   template <class T>
   Enable_if<true, T> f0(int x) {};
};

int main(void)
{
   X xx;
   xx.f0<void>(0);
   return 0;
}

I understand the case in the prior mentioned thread for a construct:

template <typename enable_if<false>::type* = nullptr> 
void f0() {}

this is because the template parameter is ill-formed (no ::type to assign nullptr to.)

Upvotes: 2

Views: 254

Answers (1)

JeJo
JeJo

Reputation: 32722

I'm trying to understand how SFINAE omits the Enable_if<false, T> f0(int x) {}; construct. Is it because of the lack of a return type ::type makes the template construct ill-formed language-wise?

Short answer: NO!

You need to have a look, how SFNINAE basically works form a good c++ book. For instance from the cppreference.com

This rule applies during overload resolution of function templates: When substituting the explicitly specified or deduced type for the template parameter fails, the specialization is discarded from the overload set instead of causing a compile error.

Meaning, you need first of all overloaded template-functions! This has been achieved in the given example code.

Secondly, the part of std::enable_if. It checks the condition you provide in

template< bool B, class T = void >
//       ^^^^^^^ -----------------------> here!!
struct enable_if;

at compile-time and, decide whether to activate the part below or not.

The standard library component std::enable_if allows for creating a substitution failure in order to enable or disable particular overloads based on a condition evaluated at compile time.

In your code, for the given overload

template <class T>
Enable_if<false, T> f0(int x) {};
//        ^^^^^ ---------------> CONDITION == false

the condition is false, and hence in effect, this part (code) will not be there after the compiler done with the compilation.


Is it because of the lack of a return type ::type makes the template construct ill-formed language-wise?

For the reason mentioned above, NO; that is not the reason!

By providing a template-type-alias like this

template<bool B, typename T>
using Enable_if = typename std::enable_if<B,T>::type;
//                                            ^^^^^^^ --> type has been mentioned here!

you have mentioned the ::type via the alias type Enable_if</*condition*/, T>.

Upvotes: 2

Related Questions