C++模板和模糊问题
我有一个指针类的子集,它看起来像:C++模板和模糊问题
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
。然后,一切都很好。如果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;
};
明白了,好主意。该项目暂时不使用提升。任何想法如何'is_convertible'的作品? – cvb 2009-12-13 22:00:46
是的。随时upvote。:) – sellibitze 2009-12-13 22:10:56
会upvoted十倍,但我没有注册:) – cvb 2009-12-13 22:23:18
尽量让有问题明确的构造函数,例如:
template <typename t>
explicit Pointer(const Pointer<t> &x);
和/或删除operator T *() const;
- 我想,这其中也将产生歧义。
编辑
检查std::auto_ptr接口,并与你进行比较。至少他们解决了歧义。
将'explicilt'添加到声明中会产生相同的效果:它会生成一个编译错误(2个重载都不能转换所有参数类型...)。移除铸造操作符并不能解决amibguity问题(无论如何,它是这个类的宝贵部分)。 – cvb 2009-12-13 21:49:09
您可以添加代码,使用指针,请添加(作为注释)出现编译错误的位置,以及哪个错误。 – Frunsi 2009-12-13 21:58:11
虽然铸造操作员仍然可能是造成这种困境的原因(正如Alexey指出的那样) ,隐式转换是一个糟糕的主意:std :: auto_ptr没有添加它,并且boost ptrs不会因为相同的原因添加它(在某些情况下是ambuigity)。 – Frunsi 2009-12-13 22:00:52
这是更为常见的使用大写字母'U'额外的模板参数。小写't'几乎看起来像一个错字。 – GManNickG 2009-12-13 21:43:57
隐式转换是一个坏主意。使用'T * get()'而不是'运算符T *()'。 shared_ptr做这样的事情。 – 2009-12-13 21:49:38