I’m writing a set of C++ parameterized classes and I’m interested in some of them behaving similarly to pointers. In particular, I want to be able to create an object with a constant template parameter from an object with a non-constant template parameter, but not the other way around. This sample code should clarify my intentions:
int main() {
myClass<int> mc_int;
myClass<const int> mc_const_int;
myClass<const int> mc1(mc_const_int); // This should compile.
myClass<int> mc2(mc_int); // This should compile.
myClass<const int> mc3(mc_int); // This should compile.
myClass<int> mc4(mc_const_int); // This should NOT compile.
}
I have been able to achieve this particular behavior by creating the next class hierarchy (simplified for readability):
template <typename T>
class Base {
// ...
protected:
template <typename U>
Base(const Base<U> &obj): _elem(obj._elem) {}
private:
T _elem;
friend class Base<const T>;
};
template <typename T>
class myClass: public Base<T> {
// ...
public:
template <typename U>
myClass(const myClass<U> &obj): Base<const U>(obj) {}
};
And it works as expected, but I’m not entirely satisfied with this design because I can only detect a non-constant template parameter from the constructor, but not from any other member function.
If I wanted, for example, to create a container class with an addAll() method, I would like to be able to do this:
int main() {
Container<int> c_int;
c_int.add(new int(1));
c_int.add(new int(2));
c_int.add(new int(3));
Container<const int> c_const_int;
c_const_int.addAll(c_int); // This should compile.
c_int.addAll(c_const_int); // This should NOT compile.
}
But I don’t know how to achieve the previous behavior. Does anyone have ideas for an alternate design to achieve what I’m trying to do? Does anyone know of a link where this problem is discussed in more depth?
Thanks in advance.
One way to do this is via partial template specialisation. You should define the class for non-
consttypes as you usually would:Then define a specialisation
Unfortunately, this leads to code duplication, but it should allow you to do what you want. Naturally, you can have the functions take
MyClass<T>&andMyClass<T const>&, too.