keyboard
keyboard

Reputation: 2355

C++ Templates - Add function only if certain value in template parameter

Is what I'm trying here possible somehow?

I know that #if doesn't work with template parameters.

Please don't teach me how properties are against the idea of C++, that's not the question here.

typedef enum {
kPropertyReadWrite,
kPropertyReadOnly
} PropertyType;


template <typename T, PropertyType P = kPropertyReadWrite>
class property {
  T value;
public:
  property() {}
  property(T initValue) : value(initValue){}


#if P == kPropertyReadOnly
  T & operator = (const T &i) {
    //::std::cout << i << ::std::endl;

    return value = i;
  }
#endif

  operator T const & () const {
    return value;
  }
};

Upvotes: 4

Views: 3776

Answers (3)

Dimitrios Bouzas
Dimitrios Bouzas

Reputation: 42929

You could provide a template specialization:

typedef enum {
kPropertyReadWrite,
kPropertyReadOnly
} PropertyType;

template <typename T, PropertyType = kPropertyReadWrite>
class property {
  T value;
public:
  property() {}
  property(T initValue) : value(initValue){}

  operator T const & () const {
    return value;
  }
};

template <typename T>
class property<T, kPropertyReadOnly> {
  T value;
public:
  property() {}
  property(T initValue) : value(initValue){}

  T & operator = (const T &i) {
    std::cout << i << ::std::endl;
    return value = i;
  }

  operator T const & () const {
    return value;
  }
};

Live Demo

Upvotes: 1

Jack
Jack

Reputation: 133609

This is easily achieved through std::enable_if:

template<PropertyType U = P, typename std::enable_if<P == kPropertyReadWrite, int>::type = 0> T& operator=(const T &i)
{ 
  return value = i;
}

This works by disabling the method if the condition is not met during compilation, raising a compilation error in this situation (or choosing another enabled implementation in a different scenario)

Upvotes: 2

T.C.
T.C.

Reputation: 137425

I'm surprised that so many people can't get the SFINAE right. The SFINAE condition needs to depend on a template parameter of operator=, and not the class template. Otherwise, instantiating the class template may cause a hard error.

template<PropertyType P1 = P, typename std::enable_if<P1 != kPropertyReadOnly, int>::type = 0>
T & operator = (const T &i) {
  //::std::cout << i << ::std::endl;

  return value = i;
}

Note that this is actually not sufficient to prevent property<int, kPropertyReadOnly> p2; p2 = 10; from compiling, because your code defines an implicit conversion from T to property<T, ...>, so the compiler will implicitly convert the 10 to a property and then call the copy assignment operator.

Upvotes: 3

Related Questions