I encountered something I can’t explain when trying to build an existing codebase with the newer c++ standard.
The following snippet compiles with c++17 but fails with c++20
#include <sstream>
int main() {
std::basic_stringstream<char> ss;
char c = 'a';
ss >> &c;
return 1;
}
Compilation error:
<source>:6:8: error: no match for 'operator>>' (operand types are 'std::__cxx11::basic_stringstream<char>' and 'char*')
6 | ss >> &c;
| ~~ ^~ ~~
| | |
| | char*
| std::__cxx11::basic_stringstream<char>
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/sstream:40,
from <source>:1:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:170:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(bool&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
170 | operator>>(bool& __n)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:170:7: note: conversion of argument 1 would be ill-formed:
<source>:6:11: error: cannot bind non-const lvalue reference of type 'bool&' to a value of type 'char*'
6 | ss >> &c;
| ^~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:174:7: note: candidate: 'std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(short int&) [with _CharT = char; _Traits = std::char_traits<char>]' (near match)
174 | operator>>(short& __n);
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:174:7: note: conversion of argument 1 would be ill-formed:
<source>:6:11: error: invalid conversion from 'char*' to 'short int' [-fpermissive]
6 | ss >> &c;
| ^~
| |
| char*
<source>:6:11: error: cannot bind rvalue '(short int)(& c)' to 'short int&'
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:177:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(short unsigned int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
177 | operator>>(unsigned short& __n)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:177:7: note: conversion of argument 1 would be ill-formed:
<source>:6:11: error: invalid conversion from 'char*' to 'short unsigned int' [-fpermissive]
6 | ss >> &c;
| ^~
| |
| char*
<source>:6:11: error: cannot bind rvalue '(short unsigned int)(& c)' to 'short unsigned int&'
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:181:7: note: candidate: 'std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(int&) [with _CharT = char; _Traits = std::char_traits<char>]' (near match)
181 | operator>>(int& __n);
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:181:7: note: conversion of argument 1 would be ill-formed:
<source>:6:11: error: invalid conversion from 'char*' to 'int' [-fpermissive]
6 | ss >> &c;
| ^~
| |
| char*
<source>:6:11: error: cannot bind rvalue '(int)(& c)' to 'int&'
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:184:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(unsigned int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
184 | operator>>(unsigned int& __n)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:184:7: note: conversion of argument 1 would be ill-formed:
<source>:6:11: error: invalid conversion from 'char*' to 'unsigned int' [-fpermissive]
6 | ss >> &c;
| ^~
| |
| char*
<source>:6:11: error: cannot bind rvalue '(unsigned int)(& c)' to 'unsigned int&'
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:188:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
188 | operator>>(long& __n)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:188:7: note: conversion of argument 1 would be ill-formed:
<source>:6:11: error: invalid conversion from 'char*' to 'long int' [-fpermissive]
6 | ss >> &c;
| ^~
| |
| char*
<source>:6:11: error: cannot bind rvalue '(long int)(& c)' to 'long int&'
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:192:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long unsigned int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
192 | operator>>(unsigned long& __n)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:192:7: note: conversion of argument 1 would be ill-formed:
<source>:6:11: error: invalid conversion from 'char*' to 'long unsigned int' [-fpermissive]
6 | ss >> &c;
| ^~
| |
| char*
<source>:6:11: error: cannot bind rvalue '(long unsigned int)(& c)' to 'long unsigned int&'
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:197:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long long int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
197 | operator>>(long long& __n)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:197:7: note: conversion of argument 1 would be ill-formed:
<source>:6:11: error: invalid conversion from 'char*' to 'long long int' [-fpermissive]
6 | ss >> &c;
| ^~
| |
| char*
<source>:6:11: error: cannot bind rvalue '(long long int)(& c)' to 'long long int&'
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:201:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long long unsigned int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
201 | operator>>(unsigned long long& __n)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:201:7: note: conversion of argument 1 would be ill-formed:
<source>:6:11: error: invalid conversion from 'char*' to 'long long unsigned int' [-fpermissive]
6 | ss >> &c;
| ^~
| |
| char*
<source>:6:11: error: cannot bind rvalue '(long long unsigned int)(& c)' to 'long long unsigned int&'
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:325:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(void*&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
325 | operator>>(void*& __p)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:325:7: note: conversion of argument 1 would be ill-formed:
<source>:6:11: error: cannot bind non-const lvalue reference of type 'void*&' to an rvalue of type 'void*'
6 | ss >> &c;
| ^~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:216:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(float&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]'
216 | operator>>(float& __f)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:216:25: note: no known conversion for argument 1 from 'char*' to 'float&'
216 | operator>>(float& __f)
| ~~~~~~~^~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:220:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(double&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]'
220 | operator>>(double& __f)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:220:26: note: no known conversion for argument 1 from 'char*' to 'double&'
220 | operator>>(double& __f)
| ~~~~~~~~^~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:224:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long double&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]'
224 | operator>>(long double& __f)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:224:31: note: no known conversion for argument 1 from 'char*' to 'long double&'
224 | operator>>(long double& __f)
| ~~~~~~~~~~~~~^~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:122:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(__istream_type& (*)(__istream_type&)) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]'
122 | operator>>(__istream_type& (*__pf)(__istream_type&))
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:122:36: note: no known conversion for argument 1 from 'char*' to 'std::basic_istream<char>::__istream_type& (*)(std::basic_istream<char>::__istream_type&)' {aka 'std::basic_istream<char>& (*)(std::basic_istream<char>&)'}
122 | operator>>(__istream_type& (*__pf)(__istream_type&))
| ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:126:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(__ios_type& (*)(__ios_type&)) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>; __ios_type = std::basic_ios<char>]'
126 | operator>>(__ios_type& (*__pf)(__ios_type&))
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:126:32: note: no known conversion for argument 1 from 'char*' to 'std::basic_istream<char>::__ios_type& (*)(std::basic_istream<char>::__ios_type&)' {aka 'std::basic_ios<char>& (*)(std::basic_ios<char>&)'}
126 | operator>>(__ios_type& (*__pf)(__ios_type&))
| ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:133:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(std::ios_base& (*)(std::ios_base&)) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]'
133 | operator>>(ios_base& (*__pf)(ios_base&))
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:133:30: note: no known conversion for argument 1 from 'char*' to 'std::ios_base& (*)(std::ios_base&)'
133 | operator>>(ios_base& (*__pf)(ios_base&))
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:349:7: note: candidate: 'std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(__streambuf_type*) [with _CharT = char; _Traits = std::char_traits<char>; __streambuf_type = std::basic_streambuf<char>]'
349 | operator>>(__streambuf_type* __sb);
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:349:36: note: no known conversion for argument 1 from 'char*' to 'std::basic_istream<char>::__streambuf_type*' {aka 'std::basic_streambuf<char>*'}
349 | operator>>(__streambuf_type* __sb);
| ~~~~~~~~~~~~~~~~~~^~~~
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/string:55,
from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ios:44,
from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:40:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/basic_string.tcc:835:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::basic_istream<_CharT, _Traits>& std::operator>>(basic_istream<_CharT, _Traits>&, __cxx11::basic_string<_CharT, _Traits, _Allocator>&)'
835 | operator>>(basic_istream<_CharT, _Traits>& __in,
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/basic_string.tcc:835:5: note: template argument deduction/substitution failed:
<source>:6:12: note: mismatched types 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator>' and 'char*'
6 | ss >> &c;
| ^
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/memory_resource.h:38,
from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/string:67:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/cstddef:131:5: note: candidate: 'template<class _IntegerType> constexpr std::__byte_op_t<_IntegerType> std::operator>>(byte, _IntegerType)'
131 | operator>>(byte __b, _IntegerType __shift) noexcept
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/cstddef:131:5: note: template argument deduction/substitution failed:
<source>:6:5: note: cannot convert 'ss' (type 'std::__cxx11::basic_stringstream<char>') to type 'std::byte'
6 | ss >> &c;
| ^~
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:1106:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/istream.tcc:975:5: note: candidate: 'template<class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(basic_istream<_CharT, _Traits>&, _CharT&)'
975 | operator>>(basic_istream<_CharT, _Traits>& __in, _CharT& __c)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/istream.tcc:975:5: note: template argument deduction/substitution failed:
<source>:6:12: note: deduced conflicting types for parameter '_CharT' ('char' and 'char*')
6 | ss >> &c;
| ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:846:5: note: candidate: 'template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(basic_istream<char, _Traits>&, unsigned char&)'
846 | operator>>(basic_istream<char, _Traits>& __in, unsigned char& __c)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:846:5: note: template argument deduction/substitution failed:
<source>:6:11: note: cannot convert '& c' (type 'char*') to type 'unsigned char&'
6 | ss >> &c;
| ^~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:851:5: note: candidate: 'template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(basic_istream<char, _Traits>&, signed char&)'
851 | operator>>(basic_istream<char, _Traits>& __in, signed char& __c)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:851:5: note: template argument deduction/substitution failed:
<source>:6:11: note: cannot convert '& c' (type 'char*') to type 'signed char&'
6 | ss >> &c;
| ^~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:949:5: note: candidate: 'template<class _CharT, class _Traits, long unsigned int _Num> std::basic_istream<_CharT, _Traits>& std::operator>>(basic_istream<_CharT, _Traits>&, _CharT (&)[_Num])'
949 | operator>>(basic_istream<_CharT, _Traits>& __in, _CharT (&__s)[_Num])
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:949:5: note: template argument deduction/substitution failed:
<source>:6:12: note: mismatched types '_CharT [_Num]' and 'char*'
6 | ss >> &c;
| ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:958:5: note: candidate: 'template<class _Traits, long unsigned int _Num> std::basic_istream<char, _Traits>& std::operator>>(basic_istream<char, _Traits>&, unsigned char (&)[_Num])'
958 | operator>>(basic_istream<char, _Traits>& __in, unsigned char (&__s)[_Num])
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:958:5: note: template argument deduction/substitution failed:
<source>:6:12: note: mismatched types 'unsigned char [_Num]' and 'char*'
6 | ss >> &c;
| ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:963:5: note: candidate: 'template<class _Traits, long unsigned int _Num> std::basic_istream<char, _Traits>& std::operator>>(basic_istream<char, _Traits>&, signed char (&)[_Num])'
963 | operator>>(basic_istream<char, _Traits>& __in, signed char (&__s)[_Num])
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:963:5: note: template argument deduction/substitution failed:
<source>:6:12: note: mismatched types 'signed char [_Num]' and 'char*'
6 | ss >> &c;
| ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:1096:5: note: candidate: 'template<class _Istream, class _Tp> _Istream&& std::operator>>(_Istream&&, _Tp&&)'
1096 | operator>>(_Istream&& __is, _Tp&& __x)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:1096:5: note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream: In substitution of 'template<class _Istream, class _Tp> _Istream&& std::operator>>(_Istream&&, _Tp&&) [with _Istream = std::__cxx11::basic_stringstream<char>&; _Tp = char*]':
<source>:6:12: required from here
6 | ss >> &c;
| ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:1096:5: error: template constraint failure for 'template<class _Is, class _Tp> requires (__derived_from_ios_base<_Is>) && requires(_Is& __is, _Tp&& __t) {__is >> (forward<_Tp>)(__t);} using std::__rvalue_stream_extraction_t = _Is&&'
1096 | operator>>(_Istream&& __is, _Tp&& __x)
| ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:1096:5: note: constraints not satisfied
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:41:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ostream: In substitution of 'template<class _Is, class _Tp> requires (__derived_from_ios_base<_Is>) && requires(_Is& __is, _Tp&& __t) {__is >> (forward<_Tp>)(__t);} using std::__rvalue_stream_extraction_t = _Is&& [with _Is = std::__cxx11::basic_stringstream<char>&; _Tp = char*]':
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/istream:1096:5: required by substitution of 'template<class _Istream, class _Tp> _Istream&& std::operator>>(_Istream&&, _Tp&&) [with _Istream = std::__cxx11::basic_stringstream<char>&; _Tp = char*]'
<source>:6:12: required from here
6 | ss >> &c;
| ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ostream:774:13: required for the satisfaction of '__derived_from_ios_base<_Is>' [with _Is = std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&]
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ostream:774:39: note: the expression 'is_class_v<_Tp> [with _Tp = std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&]' evaluated to 'false'
774 | concept __derived_from_ios_base = is_class_v<_Tp>
| ^~~~~~~~~~~~~~~
Compiler returned: 1
Questions
- Why is this happening?
- What fixes can be used to make the code compile and behave as with c++17?
1