假设我有一个以void *
为参数的函数。我想将此函数重载到其他指针类型,但禁止从其他指针类型到void *
的隐式转换(并且只有该转换)。我仍然希望隐式转换为基类类型成功。
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;
}
Matt Wilson将防止隐式转换为指向void的指针称为Pedantic Pointer Idiom,它在实现类型安全流和日志记录时非常有用。
他的实现使用模板外观,该模板外观使用虚指针到指针参数调度到实现。这利用了Foo**
不能隐式转换为void**
的事实。我想避免第二个论点的开销。
template <typename T> Stream & operator<<(Stream & s, T const* t)
{
return dump(s, t, &t);
}
答案 0 :(得分:1)
解决它的一种方法是将操作符专门用于void类型。这样就不需要声明Stream & dump(Stream &, void const*)
,因此可以解决问题。
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;
}