[解決済み] C++11 テンプレートパラメータを指定した make_pair がコンパイルされない
質問
私はちょうど g++ 4.7 (後のスナップショットの 1 つ) で -std=c++11 を有効にして遊んでいたところです。私の既存のコード ベースのいくつかをコンパイルしようとしましたが、失敗した 1 つのケースが私をやや困惑させました。
何が起こっているのか、誰かが説明してくれるとありがたいのですが。
以下がそのコードです。
#include <utility>
#include <iostream>
#include <vector>
#include <string>
int main ( )
{
std::string s = "abc";
// 1 ok
std::pair < std::string, int > a = std::make_pair ( s, 7 );
// 2 error on the next line
std::pair < std::string, int > b = std::make_pair < std::string, int > ( s, 7 );
// 3 ok
std::pair < std::string, int > d = std::pair < std::string, int > ( s, 7 );
return 0;
}
私は、make_pairは というのは は(1)のケースとして使うものだと理解しています(型を指定するなら(3)の方がいいかもしれません)。しかし、なぜこのケースで失敗するのかが理解できません。
正確なエラーは
test.cpp: In function ‘int main()’:
test.cpp:11:83: error: no matching function for call to ‘make_pair(std::string&, int)’
test.cpp:11:83: note: candidate is:
In file included from /gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/utility:72:0,
from test.cpp:1:
/gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/stl_pair.h:274:5:
note: template<class _T1, class _T2> constexpr std::pair<typename std::__decay_and_strip<_T1>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&)
/gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/stl_pair.h:274:5:
note: template argument deduction/substitution failed:
test.cpp:11:83: note: cannot convert ‘s’ (type ‘std::string {aka std::basic_string<char>}’) to type ‘std::basic_string<char>&&’
繰り返しますが、ここでの質問はただ単に "何が起こっているのか "テンプレート仕様を削除することで問題を解決できることは分かっていますが、私はただ、ここで何が失敗しているのかを知りたいだけなのです。
- g++ 4.4 は問題なくこのコードをコンパイルします。
- std=c++11 を削除しても、このコードは問題なくコンパイルされます。
どのように解決するのですか?
これは、どのように
std::make_pair
は意図された使い方ではありません。テンプレートの引数を明示的に指定することは想定されていません。
C++11 の
std::make_pair
は2つの引数を取り、その型は
T&&
と
U&&
であり、ここで
T
と
U
はテンプレート型のパラメータです。 実質的には次のようになります(戻り値の型は無視します)。
template <typename T, typename U>
[return type] make_pair(T&& argT, U&& argU);
を呼び出すと
std::make_pair
を呼び出し、テンプレートの型引数を明示的に指定すると、 引数の推論は行われません。 その代わり、型引数はテンプレート宣言に直接代入され、結果が得られます。
[return type] make_pair(std::string&& argT, int&& argU);
これらのパラメータタイプは両方ともrvalueの参照であることに注意してください。 したがって、これらはrvalueにのみバインドすることができます。 これは、渡す2番目の引数については問題ではありません。
7
はrvalue式だからです。
s
は、しかし、lvalue式です(それは一時的ではなく、移動されていない)。 これは、関数テンプレートが引数にマッチしないことを意味し、それがエラーになる理由です。
では、なぜ明示的に何を指定しないときに動作するのかというと、それは
T
と
U
はテンプレートの引数リストにあるのでしょうか? 要するに、rvalueの参照パラメータはテンプレートでは特別なのです。 という言語機能のせいもありますが
参照折りたたみ
という言語機能により、rvalue の参照パラメータは
A&&
で、ここで
A
はテンプレート型パラメータで、任意の種類の
A
.
は関係ありません。
A
が lvalue か rvalue か、const-qualified か volatile-qualified か、unqualified かは関係ありません。
A&&
はそのオブジェクトにバインドすることができます(繰り返しますが、もし
A
がそれ自身テンプレート・パラメータである場合に限ります)。
あなたの例では、呼び出しを行います。
make_pair(s, 7)
ここで
s
はlvalueで
std::string
であり
7
は型のrvalue
int
. 関数テンプレートのテンプレート引数を指定していないため,テンプレート引数推論が行われ,引数が何であるかが判明します.
を結合するには
s
を、l値である
T&&
に変換すると、コンパイラは
T
は
std::string&
の引数を生成し、その引数は
std::string& &&
. しかし、参照に対する参照は存在しないので、この二重参照は崩れて
std::string&
.
s
が一致します。
を束ねるのは簡単です。
7
を
U&&
: コンパイラが推論できるのは
U
を
int
のパラメータを生成します。
int&&
という型のパラメータを生成し、それがうまく
7
はrvalueであるため、正常に結合されます。
これらの新しい言語機能には微妙な点がたくさんありますが、ある簡単なルールに従えば、とても簡単なことなのです。
もしテンプレートの引数が関数の引数から推測できるのであれば、それを推測させればよいのです。 絶対に必要でない限り、明示的に引数を提供する必要はありません。
コンパイラに難しい仕事をさせれば、99.9%はあなたが望んだとおりのものになるでしょう。 そして、99.9%はあなたが望んだとおりになります。あなたが望んだものでないとき、通常はコンパイルエラーが出ますが、これは識別して修正するのが簡単です。
関連
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] テスト
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された