假设标题
中有以下定义namespace someNamespace {
template<class T, class S>
int operator + (const T & t, const S & s) {
return specialAdd (t, s);
}
}
现在我希望标题的用户能够执行类似
的操作using someNamespace::operator + <OneClass,SecondClass>;
这显然是不可能的。
这样做的原因是我不希望我的运算符+干扰标准运算符+,因此让用户可以指定运算符+应该定义的类型。有没有办法实现这个目标?
答案 0 :(得分:3)
使用barton-nackman技巧:http://en.wikipedia.org/wiki/Barton%E2%80%93Nackman_trick
template<typename T,typename S>
class AddEnabled{
friend int operator + (T const& t, const S & s) {
T temp(t);
return temp.add(s);
}
};
class MyClass: public AddEnabled<MyClass,int>{
public:
MyClass(int val):mVal(val){
}
int add(int s){
mVal+=s;
return mVal;
}
private:
int mVal;
};
这是另一个重载&lt;&lt;&lt;&lt;操作者:
template<typename T>
class OutEnabled {
public:
friend std::ostream& operator<<(std::ostream& out, T const& val) {
return static_cast<OutEnabled<T> const&>(val).ioprint(out);
}
protected:
template<typename U>
U& ioprint(U& out) const {
return static_cast<T const*>(this)->print(out);
}
};
要使用它,您可以让您的类继承自OutEnabled:
class MyClass: public OutEnabled<MyClass>{ ...
或者您可以定义一个哨兵对象,例如在cpp文件中的匿名命名空间
namespace{
OutEnabled<MyClass> sentry;
}
一旦模板OutEnabled被实例化(OutEnabled<MyClass>
)GLOBAL运算符std::ostream& operator<<(std::ostream& out, MyClass const& val)
存在。
此外,MyClass必须包含匹配
的函数(模板) template<typename U>
U& print(U& out) const {
out << mBottomLeft << "\t"<< mW << "\t"<< mH;
return out;
}
由ioprint
调用。
函数U& ioprint(U& out)
并非绝对必要,但如果您在print
中没有定义MyClass
,则会为您提供更好的错误消息。
答案 1 :(得分:1)
他们可以专门化的类型特征类,以及运算符+中的enable_if?将operator +放在全局命名空间中,但它返回
std::enable_if< for::bar<c1>::value && for::bar<c2>::value, int >
其中bar是模板类型在命名空间中的traits类,如下所示:
template<class T>
struct bar: std::false_type {};
我认为这应该导致sfinae制作你的模板加上你专门接受的匹配内容。
您可能希望将一些deconst和ref剥离到enable_if中,并在运算符+中进行一些完美的转发。