Problem with SFINAE

2019-05-01 01:50发布

问题:

Why this code (fnc value in class M) do not get resolved by SFINAE rules? I'm getting an error:

Error   1   error C2039: 'type' : is not a member of
                                   'std::tr1::enable_if<_Test,_Type>'  

Of course type is not a member, it isn't defined in this general ver of enable_if but isn't the whole idea behind this to enable this ver of fnc if bool is true and do not instantiate it if it's false? Could please someone explain that to me?

#include <iostream>
#include <type_traits>

using namespace std;

template <class Ex> struct Null;
template <class Ex> struct Throw;

template <template <class> class Policy> struct IsThrow;

template <> struct IsThrow<Null> {
    enum {value = 0};
};

template <> struct IsThrow<Throw> {
    enum {value = 1};
};

template <template <class> class Derived>
struct PolicyBase {
    enum {value = IsThrow<Derived>::value};
};

template<class Ex>
struct Null : PolicyBase<Null> { };

template<class Ex>
struct Throw : PolicyBase<Throw> { } ;

template<template< class> class SomePolicy>
struct M {

  //template<class T>
  //struct D : SomePolicy<D<T>>
  //{
  //};
  static const int ist = SomePolicy<int>::value;
  typename std::enable_if<ist, void>::type value() const
  {
    cout << "Enabled";
  }

  typename std::enable_if<!ist, void>::type value() const
  {
    cout << "Disabled";
  }
};

int main()
{
    M<Null> m;
    m.value();
}

回答1:

SFINAE does not work for non-template functions. Instead you can e.g. use specialization (of the class) or overload-based dispatching:

template<template< class> class SomePolicy>
struct M
{
    static const int ist = SomePolicy<int>::value;        
    void value() const { 
        inner_value(std::integral_constant<bool,!!ist>()); 
    }
 private:
    void inner_value(std::true_type) const { cout << "Enabled"; }
    void inner_value(std::false_type) const { cout << "Disabled"; }
};


回答2:

There is no sfinae here.

After M<Null> is known the variable ist is known also. Then std::enable_if<ist, void> is well-defined too. One of your function is not well-defined.

SFINAE works only for the case of template functions. Where are template functions?

Change your code to

template<int> struct Int2Type {}

void value_help(Int2Type<true> ) const { 
    cout << "Enabled"; 
} 

void value_help(Int2Type<false> ) const { 
    cout << "Disabled"; 
} 

void value() const { 
    return value_help(Int2Type<ist>());
}