3

我有一个指针类的子集,如下所示:

template <typename T>
struct Pointer
{
     Pointer();
     Pointer(T *const x);
     Pointer(const Pointer &x);
     template <typename t>
     Pointer(const Pointer<t> &x);

     operator T *() const;
};

最后一个构造函数的目标是允许传递一个Pointer子类,或者基本上任何可以隐式转换为的类型T *。此实际规则仅由构造函数的定义强制执行,编译器无法仅通过声明来确定它。如果我放弃它,并尝试将 a 传递Pointer<Sub>给 的构造函数Pointer<Base>,我会得到一个编译错误,尽管可能通过operator T *().

虽然它解决了上述问题,但它创造了另一个问题。如果我有一个重载函数,其一个重载采用 a Pointer<UnrelatedClass>,另一个采用Pointer<BaseClass>,并且我尝试使用 a 调用它Pointer<SubClass>,我会在两个重载之间产生歧义,当然,目的是调用后一个重载。

有什么建议么?(希望我足够清楚)

4

2 回答 2

6

解决您的问题的方法称为 SFINAE(替换失败不是错误)

#include "boost/type_traits/is_convertible.hpp"
#include "boost/utility/enable_if.hpp"

template<typename T>
class Pointer {
   ...
   template<typename U>
   Pointer(const Pointer<U> &x,
      typename boost::enable_if<
         boost::is_convertible<U*,T*>
      >::type* =0)
   : ...
   {
     ...
   }
   ...
};

如果 U* 可转换为 T*,enable_if则将有一个 typedef 成员type默认为 void。然后,一切都很好。如果 U* 不能转换为 T*,则缺少此 typedef 成员,替换失败并忽略构造函数模板。

这解决了您的转换和歧义问题。

回应评论:is_convertible看起来像这样:

typedef char one;         // sizeof == 1  per definition
struct two {char c[2];};  // sizeof != 1

template<typename T, typename U>
class is_convertible {
    static T source();
    static one sink(U);
    static two sink(...);
public:
    static const bool value = sizeof(sink(source()))==1;
};
于 2009-12-13T21:46:29.443 回答
0

尝试使有问题的构造函数显式,例如:

 template <typename t>
 explicit Pointer(const Pointer<t> &x);

和/或删除operator T *() const;- 我认为这也会造成歧义。

编辑

检查std::auto_ptr接口,并与你的比较。至少他们解决了歧义。

于 2009-12-13T21:42:19.907 回答