3

ヘッダーに次の定義があるとします。

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ファイルの匿名名前空間でsentryオブジェクトを定義できます

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 に答える