Reputation: 141
I am trying to implement some kind of wrapper template for memory management purposes:
template<typename T>
class Foo {
T * var;
bool cpy;
Foo(T * inp, bool cpy): var(inp), cpy(cpy) {}
public:
// named ctors
static Foo<T> * newRef(T * inp){
return new Foo(inp, false);
}
static Foo<T> * newCpy(const Foo<T> * foo){
return new Foo(new T(*(foo->var)), true);
}
/* How to add cv variations to newCpy ? */
~Foo(){
if (cpy) delete var;
}
};
I am looking for a way to add in cv-variations in newCpy()
, such as Foo<int>::newCpy(Foo<const int> *)
and Foo<const int>::newCpy(Foo<int> *)
. My attempt looks like this:
template<typename T>
class Foo {
using mT = typename std::remove_cv<T>::type;
// T = const int -> mT = int
/* ... */
static Foo<T> * newCpy(const Foo<mT> * foo){
return new Foo(new T(*(foo->var)), true);
}
};
However this does not work for two reasons:
If T
is not const
, then mT
will be the same as T
, and the two newCpy
would have exactly the same signature as a result.
Foo<T>
does not have access to Foo<mT>::var
Is there any way around this?
Upvotes: 0
Views: 432
Reputation: 46
An inversion of the const type qualifier can be achieved with the use of the meta-function conditional
: https://en.cppreference.com/w/cpp/types/conditional
The following code requires C++17, however, to convert to C++14 simply replace occurrences of _v
with ::value
.
template <typename T>
using invert_const =
std::conditional_t<std::is_const_v<T>, std::remove_const_t<T>, const T>;
For this particular question, the example use-case would then be
static Foo<T> * newCpy(const Foo<invert_const<T>> * foo) {
return new Foo(new T(*(foo->var)), true);
}
In the example you have given, it is not clear that you intend to remove the volatile qualifier, however, if I have simply misunderstood the intended use-case, a similar inversion is possible with:
template <typename T>
using invert_volatile =
std::conditional_t<std::is_volatile_v<T>, std::remove_volatile_t<T>, volatile T>;
These may also be composed
template <typename T>
using invert_cv = invert_volatile<invert_const<T>>;
The meta-function invert_cv
may then be used in the following manner
static Foo<T> * newCpy(const Foo<invert_cv<T>> * foo) {
return new Foo(new T(*(foo->var)), true);
}
Upvotes: 1