注:この質問は本当に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);
}
まだC++ 14を読んでいないが、 'auto'は、実際に非定義関数で許可さトレーリング戻り型なしです宣言? – Angew
私は標準が何を言っているのかわかりませんが、少なくともメンバー機能のためにそれを受け入れます。私はあなたが戻り値の型に基づいてオーバーロードできないという事実に関連していると思います。 –
前者は "エラーC2995: '自動演算子+(const MyClass&const MyClass &)':関数テンプレートが既に定義されています"というエラーで失敗し、後者がコンパイルされて実行されます。 VSは組み込みの場合、VSがメンバーを複製するように見えるので、 'operator + 'の2つの定義が発生します。 –
Guvante