2015-01-14 19 views
8

注:この質問は本当にReturn type deduction for in-class friend functionsに近いですが、そこに私の問題の答えが見つかりませんでした。テンプレートの友人機能と返品タイプの控除

今もし私
#include <iostream> 

template<class T> 
class MyClass { 
    public: 
     MyClass(T const& a) : impl(a) {} 

     template<class T0, class T1> friend auto 
     // requires operator+(T0,T1) exists 
     operator+(MyClass<T0> const& a, MyClass<T1> const& b) 
     { 
      return MyClass<decltype(a.impl+b.impl)>{a.impl + b.impl}; 
     } 

     T getImpl() const { return impl; } 

    private: 
     T impl; 
}; 

int main() { 
    MyClass<int> x(2); 
    MyClass<long> y(2); 

    auto z = x+y; 
    std::cout << z.getImpl() << "\n"; 
} 

を:STD = C++ 14とstd = C++ 1Z

このコードはコンパイルでのstd = C++ 1yを持つ打ち鳴らす3.4と打ち鳴らす3.5でテスト

クラスのオペレータ+外を定義し、それはもうコンパイルされません:

template<class T> 
class MyClass { 
    public: 
     MyClass(T const& a) : impl(a) {} 

     template<class T0, class T1> friend auto 
     operator+(MyClass<T0> const& a, MyClass<T1> const& b); 

     T getImpl() const { return impl; } 
    private: 
     T impl; 
}; 

template<class T0, class T1> auto 
operator+(MyClass<T0> const& a, MyClass<T1> const& b) 
{ 
    return MyClass<decltype(a.impl+b.impl)>{a.impl + b.impl}; 
} 

クラン3.4は言う:

error: use of overloaded operator '+' is ambiguous (with operand types MyClass<int> and MyClass<long>) 

次に、クラス内の宣言とクラス外の定義の2つの異なる関数であると考えられる点を指摘します。

私の質問は:それはひどいバグですか、それともテンプレートのパラメータが友人の関数に導かれて、2つの関数が同等ではないことが導き出されるのですか? あなたは何をお勧めしますか?operator +メンバー関数を作成するか、友人演算子+をクラス内に定義します(これは私の意見ではクラスインターフェイスを混乱させるでしょう)?

私は、第三者の行列クラスをラップしようとするこのようなコードの実際の使用例を持っています。怠惰な評価のために式テンプレートを使用するため、戻り型の減算が必要です。

編集:次は仕事(まだクラッタインターフェイス...)

template<typename T> 
class MyClass 
{ 
    T impl; 

public: 
    explicit MyClass(T a) : impl(std::move(a)) { } 

    T const& getImpl() const { return impl; } 

    template<typename T0, typename T1> 
    friend auto operator +(MyClass<T0> const& a, MyClass<T1> const& b) -> MyClass<decltype(a.impl + b.impl)>; 
}; 

template<typename T0, typename T1> 
auto operator +(MyClass<T0> const& a, MyClass<T1> const& b) -> MyClass<decltype(a.impl + b.impl)> 
{ 
    return MyClass<decltype(a.impl + b.impl)>(a.impl + b.impl); 
} 
+1

まだC++ 14を読んでいないが、 'auto'は、実際に非定義関数で許可さトレーリング戻り型なしです宣言? – Angew

+0

私は標準が何を言っているのかわかりませんが、少なくともメンバー機能のためにそれを受け入れます。私はあなたが戻り値の型に基づいてオーバーロードできないという事実に関連していると思います。 –

+0

前者は "エラーC2995: '自動演算子+(const MyClass &const MyClass &)':関数テンプレートが既に定義されています"というエラーで失敗し、後者がコンパイルされて実行されます。 VSは組み込みの場合、VSがメンバーを複製するように見えるので、 'operator + 'の2つの定義が発生します。 – Guvante

答えて

1

編集ん、それはGCC 4.8.2と4.9

のバグコメント欄で 見ます

のGCCエラーコード:

prog.cpp:10:61: error: non-static data member declared 'auto' operator+(MyClass const& a, MyClass const& b) ^prog.cpp: In function 'int main()': prog.cpp:25:15: error: no match for 'operator+' (operand types are 'MyClass' and 'MyClass') auto z = x+y; ^

+4

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59766 – dyp

+0

はい、問題は何ですか?オペレータ+(MyClass 、MyClass )および演算子+(MyClass 、MyClass )は、異なるシグニチャを持ちます。したがって、異なる値を返すことがあります。 –

+0

MyClassは型ではなくテンプレートなので、Gccメッセージも奇妙です。 –

関連する問題