Why does clang allow me to use a temporary reference other than a constant in C ++ 03 mode?

Inspired by my observation in the previous question , I decided to do a little test:

#include <iostream> #include <sstream> int main() { char c = 'A'; std::stringstream ss("B"); // I know this is bad mojo; that why I'm testing it ss >> char(c); std::cout << c << std::endl; } 

My compiler version:

Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix

Compiling clang in C ++ 03 mode, it compiles and works fine:

 $ clang++ -Wall -pedantic -std=c++03 test.cpp test.cpp:9:6: warning: expression result unused [-Wunused-value] ss >> char(c); ~~ ^ ~~~~~~~ 1 warning generated. $ ./a.out A 

It outputs A , which is fine, given that this code does not even compile. Switching to C ++ 11 mode is correct for compilation errors ( error: invalid operands to binary expression ('std::stringstream' (aka 'basic_stringstream<char>') and 'int') ).

Yes, in C ++ 03, this gives a warning, but it is not a warning that I would expect (I expected some kind of warning "Accept temporary by reference" / error, or perhaps a warning / error saying "no " operator>> takes a char parameter).

My question is: why is the code compiling successfully in C ++ 03 mode? Is there any alternative operator>> overload that avoids temporary handling? Is this overly weak and let me take a temporary link? I am puzzled by why clang accepts this code at all; GCC 4.9 correctly resolves errors in C ++ 03/11 modes with a much more relevant error ( error: no match for 'operator>>' (operand types are 'std::stringstream {aka std::basic_stringstream<char>}' and 'char') ). Clang's behavior in C ++ 03 mode puzzles me.

+6
source share
1 answer

I think it calls operator bool() of std::stringstream , i.e. the code is interpreted as

 bool(ss) >> char(c); 

which, of course, is a valid statement without effect. Implicit conversion to bool returns !fail() , and this allows you to use code like

 while (ss >> foo) ... 

The standard allows you to convert to another type, which is converted to bool instead of a simple bool (for example, a void* ) to avoid this type of problem. Your implementation does not seem to use this freedom.

+2
source

Source: https://habr.com/ru/post/975226/


All Articles