2

I try to understand the enable_if implementation, which is a pair of template classes. what I do not understand, why enable_if<true, int> is not matched to the first one? how is this decided?

#include <iostream>

template <bool, class T = void>
struct enable_if
{
    enable_if() { std::cout << "invalid type";}
};

template <class T>
struct enable_if<true, T>
{
  typedef T type;
  enable_if() { std::cout <<"valid type";}
};

int main(){
    enable_if<0==0, int> example; // print "valid type"
    return 0;
}
pepero
  • 7,095
  • 7
  • 41
  • 72
  • Best fit and other stuff. If the explicit specialization can be chosen, it will be, otherwise default to base template. – DeiDei Aug 17 '16 at 21:02
  • 1
    It's called [partial ordering](http://en.cppreference.com/w/cpp/language/partial_specialization#Partial_ordering) – Praetorian Aug 17 '16 at 21:04

1 Answers1

8

There are two steps.

  1. We match the primary class template: enable_if<true, int> matches enable_if<bool, T>. If there were any default arguments on the primary, we'd populate them at this point.
  2. We enumerate all the specializations of the primary class template that also match, which would be:
    a. enable_if<bool, T>, with bool=true and T=int
    b. enable_if<true, T>, with T=int

    We pick the most specialized specialization through a process called partial ordering, which you can think of informally as picking the most specific one. In this case, (2b) is more specific than (2a) because all (2b) instantiations could match against (2a) but not the reverse, so we select that one.

And so, you end up with an instantiation enable_if<true, T> with T=int.

Barry
  • 286,269
  • 29
  • 621
  • 977