2

我想声明一个“安全”push()函数,以便auto_ptr像这样使用:

template<class StackType,typename T>
inline void push( StackType &s, auto_ptr<T> p ) {
  s.push( p.get() );
  p.release();
}

我也希望它适用于空指针,例如:

push( my_stack, 0 ); // push a null pointer

因此,专业化:

template<class StackType>
inline void push( StackType &s, int p ) {
  s.push( reinterpret_cast<typename StackType::value_type>( p ) );
} 

虽然它有效,但它既丑陋又允许错误代码,例如:

push( my_stack, 1 ); // ???

编译。

我怎样才能写出一个push()只接受0作为有效值int(对于空指针)的特化?

要求

  • StackType是一些我必须使用的类似堆栈的容器类,并且我无法更改其源代码(就像std::stack)。我可以假设它有一个push()成员函数。

  • 我不能使用nullptr,因为我不需要 C++0x 编译器。

4

3 回答 3

3

您可以按如下方式重载该函数:

template<class StackType,typename T>
inline void push( StackType &s, auto_ptr<T> p ) {
  s.push( p.get() );
  p.release();
}

template<class StackType>
inline void push( StackType &s )
{
  s.push( reinterpret_cast<typename StackType::value_type>( 0 ) );
}

然后使用它:

push( my_stack );
push( my_stack, auto_ptr_var );
于 2011-05-17T19:40:55.227 回答
1

编辑:第二次迭代。(第一个假设push某些特定堆栈类的方法将被重载。)

相反,此迭代旨在push为任何提供可以存储的 push 成员的类提供函数模板T*。目的是允许auto_ptr<T>0作为参数,但不允许其他整数值和指针。

基本技巧仍然相同:提供一个重载,以便push(s, 0)实际解释0为指向成员的空指针。

class X;

template<typename StackType, typename T>
void push(StackType& s, std::auto_ptr<T> p);

template<typename ST>
void push(ST&, int (X::*));

class X {
  private:
    int m;
    X(); // unimplemented
    X(const X&); // unimplemented
    X& operator=(const X&); // unimplemented
    ~X(); // unimplemented

   template<typename ST>
   friend
   void push(ST&, int (X::*));
};

template<typename StackType, typename T>
void push(StackType& s, std::auto_ptr<T> p) {
    s.push(p.get());
    p.release();
}

template<typename StackType>
void push(StackType& s, int (X::*)) {
    s.push(0);
}

测试:

std::stack<int*> s;
push(s, std::auto_ptr(new int(1))); // works
push(s, 0);  // works
push(s, 1);  // errors out: no matching function
于 2011-05-17T20:54:13.630 回答
0

您需要特定的空指针类型来处理这种情况。这就是 C++11 引入nullptr.

于 2011-05-17T19:42:15.220 回答