C++模板和歧义问题

标签 c++ templates ambiguity implicit-conversion 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> 调用它,我在两个重载之间有歧义,当然,意图是调用后一个重载。

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

最佳答案

解决您的问题的方法称为 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;
};

关于C++模板和歧义问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1897844/

相关文章:

c++ - 带有 Qt5 : No rule to make target 的 Netbeans

java - 在 Freemarker 中包含带有变量的模板

C++ 运算符歧义

c# - 如何解决简单的歧义

c++ - Qt connect 找不到插槽

c++ - C++ 库中的自动初始化例程?

c++ - 防止 "Program too big to fit in memory"的链接器选项

c++ - 如何将值转换为 vector

c++ - 如何获得两种不同类型相乘的结果类型?

c# - 为什么 IList<>.Reverse() 不像 List<>().Reverse 那样工作