Reputation: 2355
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
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;
}
};
Upvotes: 1
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
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