「右辺値参照宣言子: &&」
の例をclang++, g++で編纂(compile)してみた。Visual studioでの実行例は上記で掲載。今回利用した処理系は下記。機材はMacBook Pro, 2.6GHz intel Core i5, 16GB dory.
vc++ はMicrosoft Windows [Version 10.0.17134.165]上のMicrosoft(R) C/C++ Optimizing Compiler Version 19.12.25830.2 for x86
$ clang++ --version
clang version 6.0.0 (tags/RELEASE_600/final)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /usr/local/opt/llvm/bin
$ g++-8 --version
g++-8 (Homebrew GCC 8.1.0) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
例題1:string_conctenation.cpp
// string_concatenation.cpp
// compile with: /EHsc
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = string("h") + "e" + "ll" + "o";
cout << s << endl;
}
clang++, g++, vc++
$ clang++ string_conctenation.cpp -I./ -std=c++14 -Wall
hello
$ clang++ string_conctenation.cpp -I./ -std=c++17 -Wall
hello
$ clang++ string_conctenation.cpp.cpp -I./ -std=c++2a -Wall
hello
$ g++-8 string_conctenation.cpp -I./ -std=c++14 -Wall
hello
$ g++-8 string_conctenation.cpp -I./ -std=c++17 -Wall
hello
$ g++-8 ms.cpp -I./ -std=c++2a -Wall
hello
>cl string_conctenation.cpp /EHsc
Microsoft(R) C/C++ Optimizing Compiler Version 19.12.25830.2 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
string_conctenation.cpp
C:\Program Files (x86)\Microsoft Visual
Microsoft (R) Incremental Linker Version 14.12.25830.2
Copyright (C) Microsoft Corporation. All rights reserved.
/out:string_conctenation.exe
string_conctenation.obj
C:>string_conctenation.exe
hello
例題2:reference-overload.cpp
// reference-overload.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;
// A class that contains a memory resource.
class MemoryBlock
{
// TODO: Add resources for the class here.
};
void f(const MemoryBlock&)
{
cout << "In f(const MemoryBlock&). This version cannot modify the parameter." << endl;
}
void f(MemoryBlock&&)
{
cout << "In f(MemoryBlock&&). This version can modify the parameter." << endl;
}
int main()
{
MemoryBlock block;
f(block);
f(MemoryBlock());
}
clang++, g++, vc++
$ clang++ reference-overload.cpp -I./ -std=c++14 -Wall
In f(const MemoryBlock&). This version cannot modify the parameter.
In f(MemoryBlock&&). This version can modify the parameter.
$ clang++ reference-overload.cpp -I./ -std=c++17 -Wall
In f(const MemoryBlock&). This version cannot modify the parameter.
In f(MemoryBlock&&). This version can modify the parameter.
$ clang++ reference-overload.cpp -I./ -std=c++2a -Wall
In f(const MemoryBlock&). This version cannot modify the parameter.
In f(MemoryBlock&&). This version can modify the parameter.
$ g++-8 reference-overload.cpp -I./ -std=c++14 -Wall
In f(const MemoryBlock&). This version cannot modify the parameter.
In f(MemoryBlock&&). This version can modify the parameter.
$ g++-8 reference-overload.cpp -I./ -std=c++17 -Wall
In f(const MemoryBlock&). This version cannot modify the parameter.
In f(MemoryBlock&&). This version can modify the parameter.
$ g++-8 reference-overload.cpp -I./ -std=c++2a -Wall
In f(const MemoryBlock&). This version cannot modify the parameter.
In f(MemoryBlock&&). This version can modify the parameter.
>cl reference-overload.cpp /EHsc
Microsoft(R) C/C++ Optimizing Compiler Version 19.12.25830.2 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
reference-overload.cpp
C:\Program Files (x86)\Microsoft Visual
Microsoft (R) Incremental Linker Version 14.12.25830.2
Copyright (C) Microsoft Corporation. All rights reserved.
/out:reference-overload.exe
reference-overload.obj
C:>reference-overload.exe
In f(const MemoryBlock&). This version cannot modify the parameter.
In f(MemoryBlock&&). This version can modify the parameter.
例題3:named-reference.cpp
// named-reference.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;
// A class that contains a memory resource.
class MemoryBlock
{
// TODO: Add resources for the class here.
};
void g(const MemoryBlock&)
{
cout << "In g(const MemoryBlock&)." << endl;
}
void g(MemoryBlock&&)
{
cout << "In g(MemoryBlock&&)." << endl;
}
MemoryBlock&& f(MemoryBlock&& block)
{
g(block);
return block;
}
int main()
{
g(f(MemoryBlock()));
}
clang++, g++
$ clang++ named-reference.cpp -I./ -std=c++14 -Wall
named-reference.cpp:25:11: error: rvalue reference to type 'MemoryBlock' cannot bind
to lvalue of type 'MemoryBlock'
return block;
^~~~~
1 error generated.
$ clang++ named-reference.cpp -I./ -std=c++17 -Wall
named-reference.cpp:25:11: error: rvalue reference to type 'MemoryBlock' cannot bind
to lvalue of type 'MemoryBlock'
return block;
^~~~~
1 error generated.
$ clang++ named-reference.cpp -I./ -std=c++2a -Wall
named-reference.cpp:25:11: error: rvalue reference to type 'MemoryBlock' cannot bind
to lvalue of type 'MemoryBlock'
return block;
^~~~~
1 error generated.
$ g++-8 named-reference.cpp -I./ -std=c++14 -Wall
named-reference.cpp: In function 'MemoryBlock&& f(MemoryBlock&&)':
named-reference.cpp:25:11: error: cannot bind rvalue reference of type 'MemoryBlock&&' to lvalue of type 'MemoryBlock'
return block;
^~~~~
$ g++-8 named-reference.cpp -I./ -std=c++17 -Wall
named-reference.cpp: In function 'MemoryBlock&& f(MemoryBlock&&)':
named-reference.cpp:25:11: error: cannot bind rvalue reference of type 'MemoryBlock&&' to lvalue of type 'MemoryBlock'
return block;
^~~~~
$ g++-8 named-reference.cpp -I./ -std=c++2a -Wall
named-reference.cpp: In function 'MemoryBlock&& f(MemoryBlock&&)':
named-reference.cpp:25:11: error: cannot bind rvalue reference of type 'MemoryBlock&&' to lvalue of type 'MemoryBlock'
return block;
^~~~~
e>cl named-reference.cpp /EHsc
Microsoft(R) C/C++ Optimizing Compiler Version 19.12.25830.2 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
named-reference.cpp
C:\Program Files (x86)\Microsoft Visual
named-reference.cpp(25): error C2440: 'return': 'MemoryBlock' から 'MemoryBlock &&' に変換できません。
named-reference.cpp(25): note: 左辺値を右辺値の参照にバインドすることはできません
clang++, g++でエラーになる。
MSのサイトには「左辺値は右辺値参照にキャストできます。」
と書いている。clang++, g++の仕様はこれから確認。
p.s. 20180808追記
VC++でもエラーになった。
@rinse_ さんからのコメントで短い表現の方で試した。
// named-reference.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;
// A class that contains a memory resource.
class MemoryBlock
{
// TODO: Add resources for the class here.
};
void g(const MemoryBlock&)
{
cout << "In g(const MemoryBlock&)." << endl;
}
void g(MemoryBlock&&)
{
cout << "In g(MemoryBlock&&)." << endl;
}
MemoryBlock&& f(MemoryBlock&& block)
{
g(block);
return move(block);// @rinse_ teach me at comment No.1
// original is "return block;"
}
int main()
{
g(f(MemoryBlock()));
}
clang++, g++
$ clang++ named-reference2.cpp -I./ -std=c++14 -Wall
In g(const MemoryBlock&).
In g(MemoryBlock&&).
$ clang++ named-reference2.cpp -I./ -std=c++17 -Wall
In g(const MemoryBlock&).
In g(MemoryBlock&&).
$ clang++ named-reference2.cpp -I./ -std=c++2a -Wall
In g(const MemoryBlock&).
In g(MemoryBlock&&).
$ g++-8 named-reference2.cpp -I./ -std=c++14 -Wall
In g(const MemoryBlock&).
In g(MemoryBlock&&).
$ g++-8 named-reference2.cpp -I./ -std=c++17 -Wall
In g(const MemoryBlock&).
In g(MemoryBlock&&).
$ g++-8 named-reference2.cpp -I./ -std=c++2a -Wall
In g(const MemoryBlock&).
In g(MemoryBlock&&).
>cl named-reference2.cpp /EHsc
Microsoft(R) C/C++ Optimizing Compiler Version 19.12.25830.2 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
named-reference2.cpp
C:\Program Files (x86)\Microsoft Visual
Microsoft (R) Incremental Linker Version 14.12.25830.2
Copyright (C) Microsoft Corporation. All rights reserved.
/out:named-reference2.exe
named-reference2.obj
C:\Users\Administrator\source>named-reference2.exe
In g(const MemoryBlock&).
In g(MemoryBlock&&).
例題4:template-type-deduction.cpp
// template-type-deduction.cpp
// Compile with: /EHsc
#include <iostream>
#include <string>
using namespace std;
template<typename T> struct S;
// The following structures specialize S by
// lvalue reference (T&), const lvalue reference (const T&),
// rvalue reference (T&&), and const rvalue reference (const T&&).
// Each structure provides a print method that prints the type of
// the structure and its parameter.
template<typename T> struct S<T&> {
static void print(T& t)
{
cout << "print<T&>: " << t << endl;
}
};
template<typename T> struct S<const T&> {
static void print(const T& t)
{
cout << "print<const T&>: " << t << endl;
}
};
template<typename T> struct S<T&&> {
static void print(T&& t)
{
cout << "print<T&&>: " << t << endl;
}
};
template<typename T> struct S<const T&&> {
static void print(const T&& t)
{
cout << "print<const T&&>: " << t << endl;
}
};
// This function forwards its parameter to a specialized
// version of the S type.
template <typename T> void print_type_and_value(T&& t)
{
S<T&&>::print(std::forward<T>(t));
}
// This function returns the constant string "fourth".
const string fourth() { return string("fourth"); }
int main()
{
// The following call resolves to:
// print_type_and_value<string&>(string& && t)
// Which collapses to:
// print_type_and_value<string&>(string& t)
string s1("first");
print_type_and_value(s1);
// The following call resolves to:
// print_type_and_value<const string&>(const string& && t)
// Which collapses to:
// print_type_and_value<const string&>(const string& t)
const string s2("second");
print_type_and_value(s2);
// The following call resolves to:
// print_type_and_value<string&&>(string&& t)
print_type_and_value(string("third"));
// The following call resolves to:
// print_type_and_value<const string&&>(const string&& t)
print_type_and_value(fourth());
}
clang++, g++
$ clang++ template-type-deduction.cpp -I./ -std=c++14 -Wall
print<T&>: first
print<const T&>: second
print<T&&>: third
print<const T&&>: fourth
$ clang++ template-type-deduction.cpp -I./ -std=c++17 -Wall
print<T&>: first
print<const T&>: second
print<T&&>: third
print<const T&&>: fourth
$ clang++ template-type-deduction.cpp -I./ -std=c++2a -Wall
print<T&>: first
print<const T&>: second
print<T&&>: third
print<const T&&>: fourth
$ g++-8 template-type-deduction.cpp -I./ -std=c++14 -Wall
print<T&>: first
print<const T&>: second
print<T&&>: third
print<const T&&>: fourth
$ g++-8 template-type-deduction.cpp -I./ -std=c++17 -Wall
print<T&>: first
print<const T&>: second
print<T&&>: third
print<const T&&>: fourth
$ g++-8 template-type-deduction.cpp -I./ -std=c++2a -Wall
print<T&>: first
print<const T&>: second
print<T&&>: third
print<const T&&>: fourth
>cl template-type-deduction.cpp /EHsc
Microsoft(R) C/C++ Optimizing Compiler Version 19.12.25830.2 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
template-type-deduction.cpp
C:\Program Files (x86)\Microsoft Visual
Microsoft (R) Incremental Linker Version 14.12.25830.2
Copyright (C) Microsoft Corporation. All rights reserved.
/out:template-type-deduction.exe
template-type-deduction.obj
C:\Users\Administrator\source>template-type-deduction.exe
print<T&>: first
print<const T&>: second
print<T&&>: third
print<const T&&>: fourth
課題など
一つコンパイルエラーになった理由を調査中。
「error: cannot bind rvalue reference of type to lvalue of type」検索
@rinse_ さんからのコメントで短い表現の方を追記。
参考文献(reference)
一時オブジェクトの寿命と右辺値参照、ムーブセマンティクスのお話
https://qiita.com/rinse_/items/ad0cc7e351e836595c94
Effective Modern C++ Item 24: Distinguish universal references from rvalue references.
https://www.slideshare.net/mooopan/emc24
rvalue reference 完全解説
https://cpplover.blogspot.com/2009/11/rvalue-reference_23.html
C++のつまずきポイント解説 その1
https://qiita.com/_EnumHack/items/a3724dead343b5aecb4e
文書履歴(document history)
ver. 0.10 初稿 20180808 午前
ver. 0.11 @rinse_ さんのコメントに基づき追記。20180808 午後
ver. 0.12 VC++の結果追記 20180808 夕方