4

I am using a SFINAE mechanism to deduce a type. Resolve<T>::type is deduced to T if class T doesn't contain yes and it's deduced to MyClass if it contains yes.

class MyClass {};

template<typename>
struct void_ { typedef void check; };

template<typename T, typename = void>
struct Resolve { typedef T type; };

template<typename T>
struct Resolve <T, typename void_<typename T::yes>::check> {
    typedef MyClass type;
};

Now, I have the simple test classes as,

struct B1 { typedef int yes; }; // 1
struct B2 { typedef int yes; }; // 2
struct D1 {};  // 3
struct D2 : B1 {};  // 4
struct D3 : B1, B2 {}; // 5 <----

According to the logic following should be the result for above tests:

  1. Resove<B1>::type = MyClass
  2. Resove<B2>::type = MyClass
  3. Resove<D1>::type = D1
  4. Resove<D2>::type = MyClass
  5. Resove<D3>::type = MyClass or compiler error (due to ambiguity between B1, B2)

Strangely, in test case (5) it doesn't happen so. The result is,

Resolve<D3>::type = D3;

Can anyone explain, what magic is happening specially for multiple inheritance ? Not getting compiler error is a standard compliant behavior ? Here is the demo.

iammilind
  • 68,093
  • 33
  • 169
  • 336

1 Answers1

4

Why would you expect a compiler error? You know SFINAE stands for Substitution Failure Is Not An Error right?

When you substitute T by D3 the expression becames ambiguous. Due to SFINAE, this failure is not considered an error and your specialization is simply removed as a candidate. It's all about NOT getting a compiler error.

K-ballo
  • 80,396
  • 20
  • 159
  • 169
  • 1
    Correct. But in this case, there are 2 `typedef`s are coming to `D3`, through `B1` and `B2`; that's why I was expecting an error. If not error, the `type` should be `Myclass` as in case of `D2`. – iammilind Oct 10 '11 at 07:37
  • 1
    -1: This is a bad answer. First, it does not relate to the specific problem in the question. Second, it uses a very strange logic - SFINAE just means that there will not be an error as long as at least one suitable substitution can be found, and there is no ambiguity. – Björn Pollex Oct 10 '11 at 07:40
  • 1
    @Bjorn: How does it not relate? In the OP case there is no error because the specialization results in failure and the default template is a suitable substitution, and is the only one in the set so there is no ambiguity. – K-ballo Oct 10 '11 at 07:44
  • What my confusion is that, why shouldn't there be any ambiguity ? There are 2 `typedef`s involved in `D3`. 1st is coming through `B1` and 2nd one through `B2`. How come both are discarded. You can just try removing either of the `typedef`s and then `Resove::type = MyClass` will be the result. – iammilind Oct 12 '11 at 07:39
  • @iammilind: There **is** an ambiguity, that ambiguity is what makes that particular substitution result in a failure and that's when SFINAE kicks off and prevents that error by discarding your specialization from the viable candidates. As a result, you are left with only one candidate that provides a viable substitution -the default one-, and is the one that is picked. – K-ballo Oct 12 '11 at 07:47