単純なクラスを考えてみましょう
template< typename T >
class Wrapper {
public:
// Constructors?
private:
T wrapped;
};
効果的にするには、どのコンストラクターを使用する必要がありますか?
C++0x より前は、次のいずれかを取るコンストラクターがありました。
- const 参照 (
T const&) - タイプTが「重い」場合、 - または値 (
T) - タイプTが「ライト」の場合。
Tタイプが「重い」か「軽い」かを判断するのは簡単ではありません。
組み込み型 (ints/floats/...) のみが「軽量」であると想定できます。しかし、それは完全に正しいとは言えません。なぜなら、私たち自身Wrapper<int>も「軽い」タイプと見なされる可能性が最も高いからです。
ライブラリのようなboost::call_traitsものは、型作成者が型を「軽量」としてマークできるようにすることで、この困難を克服する手段を提供します (適切なcall_traits特殊化を提供することにより)。それ以外の場合は「重い」として扱われます。許容できるようです。
しかし、C++0x はそれをさらに悪化させます。T&&これで、(いくつかの)「重い」オブジェクトを効率的に取得できる右辺値参照 ( ) もあるからです。
このため、次の中から選択する必要があります。
- const 参照 (
T const&) のみ - タイプTが「重い」で移動セマンティクスをサポートしていない場合 (大規模な POD のように移動セマンティクスが存在しないか、何も作成されておらず、それに影響を与えていないため)、 - const 参照 (
T const&) と右辺値参照 ( )の両方T&&- typeTが「重い」で移動セマンティクスをサポートしている場合、 - 値 (
T) のみ - タイプTが「軽い」場合、または「重い」が移動セマンティクスをサポートしている場合 (コピーが作成されたとしても、それを使用する必要はありません。それ以外の場合は、T const&とにかく自分自身からコピーする必要があります...)。
どのタイプが「重い」タイプで、どのタイプが「軽い」タイプかを見分けるのはまだ簡単ではありません (以前のように)。しかし今では、型Tが移動セマンティクスをサポートしているかどうかもわかりません (またはサポートしていますか?)。
可能なコンストラクターのオーバーロードの数が指数関数的に増加するため、複数の値をラップすると、これはさらに厄介になります。
その問題の解決策はありますか?
転送 (完全転送) 引数用のテンプレート コンストラクターについて調べましたが、それが期待どおりに機能するかどうかはわかりませんでした。Tまた、コンストラクターに転送されるだけの異なる型の値を提供することもできます。これは機能と見なされる場合がありますが、そうである必要はありません。