我有一个这样的模板基类:
template<typename T, std::size_t Size>
class VectorT
{
public:
typedef T data_type;
}
Run Code Online (Sandbox Code Playgroud)
以及一些专门的派生类:
template<typename T>
class Vector2d : public VectorT<T, 2U>
{ // some specialised functions }
template<typename T>
class Vector3d : public VectorT<T, 3U>
{ // some other specialised functions }
Run Code Online (Sandbox Code Playgroud)
这些工作正常.但是,我为运营商提供了一些独立的功能.例如:
template<typename T, size_t Size>
VectorT<T, Size> operator*(T lhs, const VectorT<T, Size>& rhs)
{
...
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这些对我的派生类不起作用,因为它们返回的是a VectorT<T, Size>而不是a Vector2d<T>.
所以我尝试了
template<V>
V operator*(typename V::data_type lhs, const V& rhs)
{
...
}
Run Code Online (Sandbox Code Playgroud)
这工作正常,但它可能会导致歧义,因为它与data_type成员相混淆.
我怎样才能解决这个问题:如何编写仅适用于我的矢量库或任何衍生物的类型安全函数?
我试图绕过必须重新声明并重新定义子类的运算符.
您可以添加另一个基类,一个独立于模板参数的基类,并使用SFINAE禁用对从此类基础派生的类型以外的类型的调用:
struct VectorBase {};
template< typename T, std::size_t Size >
class VectorT : public VectorBase { ... }
template< typename V >
typename boost::enable_if< boost::is_base_of< VectorBase, V >, V >::type
operator*( V lhs, V const& rhs ){ ... }
Run Code Online (Sandbox Code Playgroud)
请注意,is_base_of< X, X >它始终是true,因此此函数将比所需的更多类型,即基类VectorBase.
如果您使用的是实现了TR1一个编译器,你可以替换boost::为std::在被用在两个地方.