I have a function void Foo(MyType* mt). I want callers to be able to pass any pointer type to this function (e.g. unique_ptr, shared_ptr or iterator) and not require passing a raw pointer. Is there any way to express this? I could write:
template <typename T>
void Foo(T t);
This will work since it will only compile if T supports operator-> and operator* which I use inside Foo, it will also only work if T has the same interface as MyType but it seems wrong to not specify in the API that I expect that template argument to be a pointer to MyType. I could also write my own wrapper:
template <typename T>
class PointerWrapper {
public:
PointerWrapper(T* t) : raw_ptr(t) {}
PointerWrapper(const std::unique_ptr<T>& t) : raw_ptr(t.get()) {}
...
private:
T* raw_ptr;
};
void Foo(PointerWrapper<MyType> mt);
This seems clunky because I will need to extend PointerWrapper for every smart pointer type under the sun.
Is there an accepted way to support this?
In C++20, you'd write a concept such as
template <typename P, typename T>
concept points_to = requires(P p) {
{ *p } -> std::common_reference_with<T &>
} && std::equality_comparable_with<std::nullptr_t>
template <points_to<MyType> T>
void Foo(T t);
Prior to that, you could write something involving std::pointer_traits
template <typename T>
std::enable_if_t<std::is_same_v<MyType, typename std::pointer_traits<T>::element_type>> Foo(T t);
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