14

次の 2 つの関数があるとします。

void ff( const std::tuple<const int&> ) { }

template < typename TT >
void gg( const std::tuple<const TT&> ) { }

そしてこれらの関数への呼び出し:

int xx = 0;
ff( std::tie( xx ) ); // passes
gg( std::tie( xx ) ); // FAILS !!

GCC 4.7.2 は最後の行のコンパイルに失敗し、次のようなエラー ノートを報告します。

note:   template argument deduction/substitution failed:
note:   types ‘const TT’ and ‘int’ have incompatible cv-qualifiers
note:   ‘std::tuple<int&>’ is not derived from ‘std::tuple<const TT&>’

最初の質問は、これが C++11 標準に適合するかどうかです。適合しない場合、その理由は何ですか?

さらに、この問題を克服するにggは、非 const 参照のタプルを渡す代わりに、const 参照のタプルを渡す必要があります (make std::tie)。これは次の方法で実行できます。

gg( std::tie( std::cref(x) ) );

ただし、追加の への呼び出しは面倒なので、const 参照のタプルを作成するstd::crefようなものがあると便利です。ctie

2 番目の質問は、ctie手動で記述する必要があるかどうかです。必要な場合、これが最善の方法ですか?

template < typename... T >
std::tuple<const T&...> ctie( const T&... args )
{
    return std::tie( args... );
}
4

1 に答える 1

4

最初の質問は、これが C++11 標準に適合するかどうかです。適合しない場合、その理由は何ですか?

これは予期される動作です。2 番目のケースでは、 となるTsoがないため、テンプレート引数の推定は失敗します。tuple<const T&>tuple<int&>

最初のケースでtuple<int&>は、暗黙的に に変換できるため、機能しtuple<const int&>ます。これはユーザー定義の変換であるため、テンプレート引数の推定では考慮されません。

あなたの質問は X/Y 問題のような匂いがします。この種の関数テンプレート/タプルの組み合わせを含むソリューションを探すようになった実際の質問を投稿することを検討してください。

関数ctieテンプレートは問題ないようです。ただし、次のようなことを覚えておいてください

auto t = ctie(5);

基本的にダングリング参照を生成します。そのため、左辺値のみに制限したい場合があります。ctie

于 2013-08-22T11:23:20.927 に答える