Reputation: 98425
Suppose that I have a function taking void *
as an argument. I'd like to overload this function to other pointer types, but disable the implicit conversion from other pointer types to void *
(and only that conversion). I still want the implicit conversion to base class types to succeed.
class Base {};
class Derived : public Base {};
class Other {};
class Stream {};
Stream & operator<<(Stream&, void *);
Stream & operator<<(Stream&, const Base*);
void test() {
Stream str;
Derived der;
Other other;
// I want the below to work
str << (void*)&der;
str << &der; // (&der) gets implicitly converted to const Base*
// But I want this to fail at either compile or link time
str << &other;
}
Prevention of implicit conversion to pointer-to-void has been called a Pedantic Pointer Idiom by Matt Wilson, and it's useful when implementing type-safe streams and logging.
His implementation uses a template facade that dispatches to am implementation with a dummy pointer-to-pointer argument. This leverages the fact that Foo**
is not implicitly convertible to void**
. I'd like to avoid the overhead of the second argument.
template <typename T> Stream & operator<<(Stream & s, T const* t)
{
return dump(s, t, &t);
}
Upvotes: 0
Views: 265
Reputation: 98425
One way of solving it is to specialize the operator for the void type. That way there's no need to declare Stream & dump(Stream &, void const*)
, thus side-stepping the problem.
template <typename T> Stream & operator<<(Stream & s, T const* t)
{
return dump(s, t);
}
template <> Stream & operator<<(Stream & s, void const * t)
{
// implement the dump here
return s;
}
Upvotes: 1