LoginSignup
1
1

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-08-08

「右辺値参照宣言子: &&」

の例を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_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
// 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
// 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-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++

$ 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
// 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 夕方

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1