3

假设header中有如下定义

namespace someNamespace {
    template<class T, class S>
    int operator + (const T & t, const S & s) {
        return specialAdd (t, s);
    }
}

现在我希望标题的用户能够执行类似的操作

using someNamespace::operator + <OneClass,SecondClass>;

这显然是不可能的。

这样做的原因是我不希望我的 operator + 干扰标准 operator +,因此让用户可以指定应该为哪些类型 operator + 定义。有没有办法做到这一点?

4

2 回答 2

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;
};

这是另一个重载 << 运算符的示例:

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)不是绝对必要的,但如果您没有printMyClass.

于 2012-11-18T11:04:26.567 回答
1

他们可以专门化的类型特征类,以及 operator+ 中的 enable_if?将 operator+ 放在全局命名空间中,但它返回

std::enable_if< for::bar<c1>::value && for::bar<c2>::value, int >

其中 bar 是命名空间中的模板类型特征类,如下所示:

template<class T>
struct bar: std::false_type {};

我认为这应该会导致 sfinae 使您的模板加上仅匹配您专门接受的内容。

你可能想在 enable_if 中加入一些 deconst 和 ref 剥离,并在你的 operator+ 中做一些完美的转发。

于 2012-11-18T10:30:56.477 回答