foo
は、lvalueまたはrvalue参照のいずれかをパラメータとして使用したいとします。rvalue参照またはlvalue参照のいずれかをとる関数を宣言する適切な方法は何ですか?
左辺値と右辺値参照を使って2つの過負荷に分解することができます。
void foo(int& a){/*some impl*/} // lvalue ref
void foo(int&& a){foo(a);} // rvalue ref
int main(){
int a;
foo(a); // lvalue
foo(1); // rvalue
}
これは動作しますが、かなり冗長です。私はテンプレートを使用して改善することができます。
template<typename T>
void foo(T &&a) { /*some impl*/ }
int main(){
int a;
foo(a); // lvalue, T = int&
foo(1); // rvalue, T = int
}
バイナリ関数の場合、テンプレートは2つのテンプレートパラメータを取る必要があります。
template<typename T1, typename T2>
void foo(T1 &&a, T2 &&b) { /*some impl*/ }
int main(){
int a;
foo(a, a); // (lvalue, lvalue), T1 = int&, T2 = int&
foo(1, 1); // (rvalue, rvalue), T1 = int, T2 = int
foo(1, a); // (rvalue, lvalue), T1 = int, T2 = int&
foo(a, 1); // (lvalue, rvalue), T1 = int&, T2 = int
}
行く方法はありますか?もっと良い方法はありますか?
私はcppを使った経験はほとんどありませんが、単に "渡されたパラメータのコピーを作成しない"と言ってもこのようなトリックをする必要があるとは思われません。
gcc 5.4.0
と-std=c++11
を使用しています。
- UPDATE 1 -
私は両方T&&
パラメータを取りstreamsライブラリrange(T&& lower, T&& upper)
方法を使用していたとき、私は、質問を思い付きました。私はlvalue
またはrvalue
の両方のパラメータを関数に渡すことができますが、パラメータとして0
とsome_var
を渡すことができません。関数の著者の理由が何であっても、私は、著者が達成したいものを犠牲にすることなく、左辺値と右辺値の混合値を取るように宣言を拡張する方法があるのか疑問に思っていました。
- UPDATE 2 - パラメータが読み取り専用である場合
const &
は(@RichardCritten)を使用することができます。
コピーしないでパラメータを変更または返す場合は、テンプレートまたは@Yakkのソリューションを使用できます。
@Yakk解決策は、複数のパラメータを取る関数を宣言すると良いでしょう。
たとえば、関数が2つのint l/r-value参照パラメータをとり、テンプレートを使用してint参照を返すと、乱雑な署名が導かれます。
template<typename T1, typename T2>
int& foo(T1 &&a, T2 &&b) {
a += b;
return a;
}
@Yakk解決策はかなりエレガントなものを与える。その後
int& foo(any_ref<int> a, any_ref<int> b) {
a += b;
return a;
}
練習のポイントは何ですか?なぜ、そのパラメータを昔のやり方で、値によって、または参照参照で取得する関数を持つことができないのですか? –
パラメータの値を変更する必要がない場合は、 'T const&'を使用してください。 –
この質問は通常、XY問題と関連しています。これについて質問した状況をより詳細に記述することができます。 –