Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with SFINAE

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();
}
like image 483
There is nothing we can do Avatar asked Nov 12 '10 12:11

There is nothing we can do


2 Answers

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"; }
};
like image 146
Georg Fritzsche Avatar answered Sep 24 '22 00:09

Georg Fritzsche


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>());
}
like image 30
Alexey Malistov Avatar answered Sep 22 '22 00:09

Alexey Malistov