Given the following situation:
template <typename T>
class Whatever
{
public:
Whatever(T &&t): _t(std::move(t)) { }
private:
T _t;
};
When T
is a pointer type, I need to check the constructor's t
arg to see if it's -1
(don't ask), and change it to a nullptr
before assigning it to _t
.
In other words, I need to overload this constructor for pointer types.
Does anyone know if this is doable?
Note: Even I partial specialize the class on pointer types, I'd want that class to inherit from the above class itself if possible (since the behaviour of both classes is identical except for this), but don't know if that's possible. Any help would be appreciated. Thanks.
You can utilize tag-dispatching and delegating constructors:
#include <type_traits>
template <typename T>
class Whatever
{
public:
Whatever(T&& t)
: Whatever(std::move(t), std::is_pointer<T>{})
{
}
private:
Whatever(T&& t, std::true_type)
: _t(/*initialize _t as a pointer*/)
{
}
Whatever(T&& t, std::false_type)
: _t(/*initialize _t as a non-pointer*/)
{
}
T _t;
};
You could faff about using std::enable_if<...>
and deal with overload sets. It is much easier to not specialize the constructor and just do the appropriate transformation differently:
template <typename T>
class WhateverBase {
protected:
T _t;
WhateverBase(T&& t): _t(std::move(t)) {}
};
template <typename T>
class WhateverBase<T*> {
protected:
T* _t;
WhateverBase(T* t): _t(adjust(t)) {}
};
template <typename T>
class Whatever: WhateverBase<T>
{
public:
Whatever(T&& t): WhateverBase(std::move(t)) {}
// ...
};
The above logic assumes there is additional code in Whatever
which is shared between the versions using different types of T
and which shouldn't be replicated.
Alternatively it would be possible to create a custom version of move()
which does the logic:
template <typename T>
std::remove_reference_t<T>&& adjust_move(T&& ref) {
return static_cast<std::remove_reference_t<T>&&>(ref);
}
template <typename T>
T* adjust_move(T* ref) { return adjust(ref); }
Whatever<T>::Whatever(T&& t): _t(adjust_move(t)) {}
(actually, this approach is simpler...).
... and use this in place of std::move(t)
in the constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With