C ++模板和歧义问题

时间:2009-12-13 21:32:19

标签: c++ templates ambiguity implicit-cast ambiguous-call

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

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 *的任何类型。这个实际规则只能由构造函数的定义强制执行,而编译器实际上无法通过声明单独解决它。如果我删除它,并尝试将Pointer<Sub>传递给Pointer<Base>的构造函数,我会收到编译错误,尽管可能有operator T *()的路径。

虽然它解决了上述问题,但却创造了另一个问题。如果我有一个重载函数,其中一个重载需要Pointer<UnrelatedClass>而另一个需要Pointer<BaseClass>,并且我尝试用Pointer<SubClass>调用它,我在两个重载之间得到一个模糊性,当然,意图是后者超载将被称为。

有什么建议吗? (希望我很清楚)

2 个答案:

答案 0 :(得分: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默认为无效。然后,一切都很好。如果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;
};

答案 1 :(得分:0)

尝试使有问题的构造函数明确,例如:

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

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

修改

检查std::auto_ptr界面,并与您的界面进行比较。至少他们解决了歧义。