https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80940
Bug ID: 80940 Summary: Private inheritance from std::ostream - compilation error for custom operator << Product: gcc Version: 7.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: witosx at gmail dot com Target Milestone: --- Even though custom operator <<(const char*) is defined compilation fails due to the implementation of std::__is_convertible_to_basic_ostream trait. This breaks code that compiled fine until libstdc++ 7.x ------------------------------------------------------------ ------------------------------------------------------------ #include <ostream> // Simple class uses private inheritance from std::ostream class MyStream : private std::ostream { public: MyStream& operator <<(const char*) { return *this; } }; int main() { MyStream stream{}; stream << "aaa"; // error in this line } ------------------------------------------------------------ ------------------------------------------------------------ /usr/include/c++/7.1.1/ostream: In instantiation of ‘struct std::__is_convertible_to_basic_ostream<MyStream&>’: /usr/include/c++/7.1.1/ostream:656:5: required by 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<_Ostream&, const _Tp&, void> >::value, typename std::__is_convertible_to_basic_ostream<_Tp>::ostream_type>::type std::operator<<(_Ostream&&, const _Tp&) [with _Ostream = MyStream&; _Tp = char [4]]’ ls.cpp:40:15: required from here /usr/include/c++/7.1.1/ostream:625:23: error: ‘std::basic_ostream<char>’ is an inaccessible base of ‘MyStream’ decltype(__check(declval<typename remove_reference<_Tp>::type*>())); ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/c++/7.1.1/ostream:625:23: error: ‘std::basic_ostream<char>’ is an inaccessible base of ‘MyStream’ ------------------------------------------------------------ ------------------------------------------------------------ The problem lies in template<typename _Tp> struct __is_convertible_to_basic_ostream { // !!! compiler picks this version of __check and fails !!! template<typename _Ch, typename _Up> static basic_ostream<_Ch, _Up>& __check(basic_ostream<_Ch, _Up>*); static void __check(...); ... }; Something like this works for me: template<typename _Ch, typename _Up> void __is_convertible_to_basic_ostream_test(basic_ostream<_Ch, _Up>*); template<typename _Tp, typename = void_t<>> struct __is_convertible_to_basic_ostream : false_type {}; template<typename _Tp> struct __is_convertible_to_basic_ostream<_Tp, void_t<decltype(__is_convertible_to_basic_ostream_test(declval<typename remove_reference<_Tp>::type*>()))>> : true_type {}; ------------------------------------------------------------ ------------------------------------------------------------ $ gcc -v :( Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --disable-multilib --disable-werror --enable-checking=release Thread model: posix gcc version 7.1.1 20170516 (GCC)