1

次のようなものを検討してください。

template <typename T> struct Foo;

template <typename S> struct Bar
{
  template <typename T> operator Foo<T>();

  // ...
};

class Baz
{
  Baz(Foo<int>&);
};

int main()
{
  Bar<float> bar;
  Baz        baz(bar); // Won't work
}

コード/コピーと貼り付けの重複を避けるために、テンプレート化された演算子を使用して一連の可能な変換を指定したいと考えています。ただし、もちろん、コードのコメント行のような一連の変換は機能しません。これは、C++ では、コンパイラがテンプレート化された演算子のすべての形式を合理的に考慮しないためです。

代わりにカット アンド ペーストを選択し、Bar を次のように定義するとします。

template <typename S> struct Bar
{
  operator Foo<int>();
  operator Foo<float>();
  // many more

  // ...
};

これで、連鎖変換を決定して見つけることができます。私が望むのは、ケーキを食べて食べることができるようにすることです。特に、演算子をテンプレートとして定義するだけでなく、変換演算子が非テンプレートとして定義されているかのように使用できる一連のガイド宣言も提供します。

template <typename S> struct Bar
{
  template <typename T> operator Foo<T>();

  template operator Foo<int>(); // Not valid C++
  template operator Foo<float>(); // Not valid C++
  // ...
};

C++11/C++14 でこれを達成する方法はありますか? 変換演算子の定義の複製を持たずに、変換演算子のインスタンス化の有限セットを個別に定義されているかのように使用できるようにするコードを構造化するための提案はありますか?

4

1 に答える 1

1

問題は変換演算子の宣言ではなく、Bazコンストラクターです。

Baz(Foo<int>&);

これは への非 const 参照を取りますFoo<int>Bar<S>aを aに暗黙的に変換するFoo<T>と、非 const 参照にバインドできない一時オブジェクトが生成されます。const への参照で引数を取るように変更すると、機能します

Baz(const Foo<int>&);

必要に応じて、特定の型に対して特定の演算子を喜んで宣言できます。

template <typename S> struct Bar
{
    template <typename T> operator Foo<T>();
    operator Foo<bool>();
};

Bar<float> a{};
Foo<int> b = a; //calls operator Foo<T>
Foo<bool> c = a; //calls operator Foo<bool>
于 2015-05-01T15:38:26.583 に答える