如何在参数重载决策中禁用隐式转换为指向空的指针?

时间:2014-02-26 17:51:34

标签: c++

动机

假设我有一个以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;
}

Pedantic Pointer Idiom

Matt Wilson将防止隐式转换为指向void的指针称为Pedantic Pointer Idiom,它在实现类型安全流和日志记录时非常有用。

他的实现使用模板外观,该模板外观使用虚指针到指针参数调度到实现。这利用了Foo**不能隐式转换为void**的事实。我想避免第二个论点的开销。

template <typename T> Stream & operator<<(Stream & s, T const* t)  
{  
  return dump(s, t, &t);
} 

1 个答案:

答案 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;
}