https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90925
Bug ID: 90925
Summary: gcc allows calling private overridden operators
Product: gcc
Version: 10.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: zhonghao at pku dot org.cn
Target Milestone: ---
My gcc is 10.0.0, and my code is:
class a {
private: template <typename b> a &operator<<(b);
};
a c();
template <typename> a fn2() {
int d;
return c() << d;
}
gcc accepts the code, but clang rejects it:
error: 'operator<<' is a private member of 'a'
return c() << d;
~~~ ^ ~
note: implicitly declared private here
template <typename b> a &operator<<(b);
^
1 error generated.
BTW, I constructed a related code sample:
#include<iostream>
using namespace std;
class A
{
public:
A():value(0){cout<<"i am gouzao"<<endl;}
A(A&):value(0){cout<<"i am gouzao"<<endl;};
~A(){cout<<"xigou"<<endl;}
A& operator++()
{
cout<<"++A"<<endl;
++value;
return *this;
}
void show()
{
cout<<"value:"<<value<<endl;
}
private:
const template <typename b> &operator++(int)
{
cout<<"A++"<<endl;
A tmp=*this;
value++;
return tmp;
}
private:
int value;
};
int main()
{
A a;
a<<1;
a.show();
a.show();
return 0;
}
The error message of gcc contains some internal messages, which can be removed:
In file included from /usr/include/c++/7/string:52:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from test.cpp:1:
/usr/include/c++/7/bits/basic_string.h:6284:5: note: candidate: template<class
_CharT, class _Traits, class _Alloc> std::basic_ostream<_CharT, _Traits>&
std::operator<<(std::basic_ostream<_CharT, _Traits>&, const
std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&)
operator<<(basic_ostream<_CharT, _Traits>& __os,
^~~~~~~~
/usr/include/c++/7/bits/basic_string.h:6284:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<_CharT,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/bits/ios_base.h:46:0,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from test.cpp:1:
/usr/include/c++/7/system_error:217:5: note: candidate: template<class _CharT,
class _Traits> std::basic_ostream<_CharT, _Traits>&
std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::error_code&)
operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
^~~~~~~~
/usr/include/c++/7/system_error:217:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<_CharT,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7/ostream:497:5: note: candidate: template<class _CharT, class
_Traits> std::basic_ostream<_CharT, _Traits>&
std::operator<<(std::basic_ostream<_CharT, _Traits>&, _CharT)
operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c)
^~~~~~~~
/usr/include/c++/7/ostream:497:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<_CharT,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7/ostream:502:5: note: candidate: template<class _CharT, class
_Traits> std::basic_ostream<_CharT, _Traits>&
std::operator<<(std::basic_ostream<_CharT, _Traits>&, char)
operator<<(basic_ostream<_CharT, _Traits>& __out, char __c)
^~~~~~~~
/usr/include/c++/7/ostream:502:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<_CharT,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7/ostream:508:5: note: candidate: template<class _Traits>
std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char,
_Traits>&, char)
operator<<(basic_ostream<char, _Traits>& __out, char __c)
^~~~~~~~
/usr/include/c++/7/ostream:508:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<char,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7/ostream:514:5: note: candidate: template<class _Traits>
std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char,
_Traits>&, signed char)
operator<<(basic_ostream<char, _Traits>& __out, signed char __c)
^~~~~~~~
/usr/include/c++/7/ostream:514:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<char,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7/ostream:519:5: note: candidate: template<class _Traits>
std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char,
_Traits>&, unsigned char)
operator<<(basic_ostream<char, _Traits>& __out, unsigned char __c)
^~~~~~~~
/usr/include/c++/7/ostream:519:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<char,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7/ostream:539:5: note: candidate: template<class _CharT, class
_Traits> std::basic_ostream<_CharT, _Traits>&
std::operator<<(std::basic_ostream<_CharT, _Traits>&, const _CharT*)
operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s)
^~~~~~~~
/usr/include/c++/7/ostream:539:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<_CharT,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/ostream:693:0,
from /usr/include/c++/7/iostream:39,
from test.cpp:1:
/usr/include/c++/7/bits/ostream.tcc:321:5: note: candidate: template<class
_CharT, class _Traits> std::basic_ostream<_CharT, _Traits>&
std::operator<<(std::basic_ostream<_CharT, _Traits>&, const char*)
operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s)
^~~~~~~~
/usr/include/c++/7/bits/ostream.tcc:321:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<_CharT,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7/ostream:556:5: note: candidate: template<class _Traits>
std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char,
_Traits>&, const char*)
operator<<(basic_ostream<char, _Traits>& __out, const char* __s)
^~~~~~~~
/usr/include/c++/7/ostream:556:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<char,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7/ostream:569:5: note: candidate: template<class _Traits>
std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char,
_Traits>&, const signed char*)
operator<<(basic_ostream<char, _Traits>& __out, const signed char* __s)
^~~~~~~~
/usr/include/c++/7/ostream:569:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<char,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7/ostream:574:5: note: candidate: template<class _Traits>
std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char,
_Traits>&, const unsigned char*)
operator<<(basic_ostream<char, _Traits>& __out, const unsigned char* __s)
^~~~~~~~
/usr/include/c++/7/ostream:574:5: note: template argument
deduction/substitution failed:
test.cpp:33:8: note: ‘A’ is not derived from ‘std::basic_ostream<char,
_Traits>’
a<<1;
^
In file included from /usr/include/c++/7/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7/ostream:682:5: note: candidate: template<class _Ostream,
class _Tp> typename
std::enable_if<std::__and_<std::__not_<std::is_lvalue_reference<_Tp> >,
std::__is_convertible_to_basic_ostream<_Ostream>, std::__is_insertable<typename
std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type, const _Tp&, void>
>::value, typename
std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type>::type
std::operator<<(_Ostream&&, const _Tp&)
operator<<(_Ostream&& __os, const _Tp& __x)
^~~~~~~~
/usr/include/c++/7/ostream:682:5: note: template argument
deduction/substitution failed:
/usr/include/c++/7/ostream: In substitution of ‘template<class _Ostream, class
_Tp> typename
std::enable_if<std::__and_<std::__not_<std::is_lvalue_reference<_Tp> >,
std::__is_convertible_to_basic_ostream<_Ostream>, std::__is_insertable<typename
std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type, const _Tp&, void>
>::value, typename
std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type>::type
std::operator<<(_Ostream&&, const _Tp&) [with _Ostream = A&; _Tp = int]’: