I'm trying to write a wrapper template class that allows conversion as if the templated type was used. I'm not sure how to write the template code to make this functional. See the code below:
class Base { }
class Derived : public Base { }
template <typename ObjectT>
class Wrapper {
...
// Implicit conversion to base types
template <class T, typename = std::enable_if_t<std::is_base_of<T, ObjectT>::value>>
operator Wrapper<T>() const {
return Wrapper<T>(data);
};
// Explicit conversion required for other types that are convertable
template <class T, typename = std::enable_if_t< std::is_convertible<ObjectT, T>::value>>
explicit operator Wrapper<T>() const {
return Wrapper<T>(data);
};
}
I would like to use Wrapper like this:
Wrapper<Base> wrapper = Wrapper<Derived>(); // Implicit conversion to base
Wrapper<float> wrapper = (Wrapper<float>)Wrapper<int>(); // float int requires explicit conversion, but is allowed
As of right now, this code gives me a compiler error since std::is_convertible<ObjectT, T> is also true for Base, Derived and thus creates the template function twice creating an ambiguous function
member function already defined or declared
CodePudding user response:
Try this:
template <typename ObjectT>
struct Wrapper {
// Implicit conversion to base types
template <class T, std::enable_if_t<std::is_base_of_v<T, ObjectT>>* = nullptr>
operator Wrapper<T>() const;
// Explicit conversion required for other types that are convertable
template <class T, std::enable_if_t<
!std::is_base_of_v<T, ObjectT> && std::is_convertible_v<ObjectT, T>>* = nullptr>
explicit operator Wrapper<T>() const;
};