16

削減されたサンプルコード:

#include <iostream>

template<typename T>
void func(T &x)
{
    std::cout << "non-const " << x << std::endl;
}

template<typename T>
void func(const T &x)
{
    std::cout << "const " << x << std::endl;
}

template<typename ...ARGS>
void proxy(ARGS ...args)
{
    func(args...);
}

int main()
{
    int i = 3;

    func(i);
    func(5);
    func("blah");

    proxy(i);
    proxy(5);
    proxy("blah");
}

期待される出力:

non-const 3
const 5
const blah
non-const 3
const 5
const blah

実際の出力:

non-const 3
const 5
const blah
non-const 3
non-const 5
non-const blah

したがってconst、可変個引数テンプレートを通過すると、どういうわけか関数パラメーターの修飾子が失われます。なんで?どうすればこれを防ぐことができますか?

PS:GCC4.5.1およびSUSE11.4でテスト済み

4

2 に答える 2

19

転送の問題に出くわすだけです。この問題は、完全転送を使用して解決されます。

std::forward基本的に、右辺値参照によってパラメーターを取得し、それらの性質を維持しながら正しく転送することに依存する必要があります。

template<typename ...Args>
void proxy(Args&& ...args)  
{
    func(std::forward<Args>(args)...);
}
于 2012-04-20T12:30:54.203 に答える
6

Luc が既に述べたように、これは転送の問題であり、それを防ぐ方法の答えは完全な転送を使用することです。しかし、最後に他の質問に対処しようとします。

そのため、関数パラメーターの const 修飾子は、可変個引数テンプレートを使用すると失われます。なんで?

これは、型推論にすべて関係しています。可変個引数テンプレートを使用していることを無視して、最も単純な 1 つの引数テンプレートを検討してください。

template <typename T>
void one_arg_proxy( T arg ) {
   func( arg );
}

あなたが持っている呼び出しの場所でone_arg_proxy( 5 )、つまり、引数はint 右辺値です。型推論は型がどうあるTべきかを判断するために開始され、ルールはそれが であることを指示するTためint、呼び出しは に変換されone_arg_proxy<int>(5)、コンパイルされるテンプレートのインスタンス化は次のようになります。

template <>
void one_arg_proxy<int>( int arg ) {
   func( arg );
}

への呼び出しfunc左辺値引数をfunc取るため、非 const 参照を取るバージョンは、 を受け取るバージョンよりも一致し (変換は不要) const&、得られる結果が得られます。ここでの問題は、 がfunc引数で呼び出されるのではproxyなく、それを作成した内部コピーで呼び出されるproxyことです。

于 2012-04-20T13:21:56.767 に答える