9

汎用参照パラメータを使用する関数テンプレートを特殊化するにはどうすればよいですか?ユニバーサル参照パラメータを使用する関数テンプレートの特殊化

foo.hpp:

template<typename T> 
void foo(T && t) // universal reference parameter 

foo.cppここ

template<> 
void foo<Class>(Class && class) { 
    // do something complicated 
} 

Classはもはや推定されるタイプではないので、正確にClassです。おそらくClass &になることはできないので、参照の折りたたみルールはここで私を助けません。 Class &パラメータを使用する別の特殊化を作成することはできますが(それはわかりませんが)、普遍的な参照が想定されているすべてのパラメータのrvalue/lvalue参照の可能な組み合わせについて、fooに含まれるコードをすべて複製することを意味します避けるために。

これを達成する方法はありますか?

はそれを解決するためのより良い方法がある場合には私の問題について具体的に:

私は、複数のゲームサーバーに接続することができ、プログラムを持っており、各サーバは、ほとんどの部分は、によってすべてを呼び出します同じ名前。しかし、いくつかのバージョンではバージョンが少し異なります。これらのことができるいくつかの異なるカテゴリがあります:移動、アイテムなど。私はコールするために内部コードの関数セットを "移動列を列挙型に移動する"という一般的な種類を書いています。機能。ただし、サーバーによっては、通信する独自​​の内部ID、文字列を使用するもの、別の状況で両方を使用するものがあります。

これでもう少し一般的なものにしたいと思います。

ServerNamespace::server_cast<Destination>(source)のようなものを呼び出せます。これにより、Moveからstd::stringまたはServerMoveIDにキャストすることができます。内部的には、一部のサーバーではメッセージの履歴を保存する必要があるため、コピーを作成する必要があります。ユニバーサルリファレンスは、この問題に対する明らかな解決策であるように思われる。

namespace ServerNamespace { 

template<typename Destination, typename Source> 
Destination server_cast(Source && source); 

} 

と実装ファイルテンプレート特殊として、すべての有効な変換を定義します:私は今、と思っていたヘッダファイル

は、単にこれは公開します。

+1

'f'は' foo'ですか?また、問題の背景は何ですか?一般的には、特殊化ではなく過負荷が必要です。 – GManNickG

+0

@GManNickGおそらく私は間違った用語を使用しました。私は私が達成しようとしていることについてより詳細に質問を編集しました –

+0

この問題に関する本当に素敵な記事は、https://mortoray.com/2013/06/03/overriding-the-broken-universal-referenceを参照してください。 -t/ –

答えて

2

私の意見では最善の解決策は、あなたがタグに過負荷タグディスパッチシステムではなく、実際の型を使用することです:行うには、最も拡張可能なものはテンプレートクラスの特殊化を作成することです

struct foo { 
    struct tag {}; 
}; 

struct bar { 
    struct tag {}; 
}; 

template<typename Destination, typename Source> 
Destination server_cast(Source && source, foo::tag) { 
    // foo 
} 

template<typename Destination, typename Source> 
Destination server_cast(Source && source, bar::tag) { 
    // bar 
} 

template<typename Destination, typename Source> 
Destination server_cast(Source && source) { 
    return server_cast<Destination>(std::forward<Source>(source), typename std::remove_reference<Source>::type::tag()); 
} 
+0

これについてもう少し考える必要があります。 –

1

を。

template< class X > struct Whatever { 
    void f(){ ... } 
}; 

template<> struct Whatever<UserType> { 
    void f(){ ... } 
}; 

私がこれを言った理由は、何でも定義するファイルの内側または外側のどこにでも特殊化を追加できるからです。

これは、Pubbyによって提案されたタグディスパッチソリューションには、非排他的ではありません。

関連する問題