「右辺値参照宣言子: &&」の例題をclang++, g++, vc++でコンパイルしてみた

#「右辺値参照宣言子: &&」
https://msdn.microsoft.com/ja-jp/library/dd293668.aspx

の例を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

```shell-session
$ 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.
```


##例題１：string_conctenation.cpp

```C++: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++

```shell-session
$ 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
```
##例題２：reference-overload.cpp 

```c++: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++

```c++:
$ 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.

```
##例題３：named-reference.cpp 

```c++: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++

```shell-session
$ 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_ さんからのコメントで短い表現の方で試した。

```c++:named-reference2.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  move(block);// @rinse_ teach me at comment No.1
// original is "return block;"  
}  
  
int main()  
{  
   g(f(MemoryBlock()));  
} 
```
clang++, g++

```shell-session
$ 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&&).
```

##例題４：template-type-deduction.cpp  

```c++: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++

```shell-session
$ 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　夕方