https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89151

            Bug ID: 89151
           Summary: SFINAE-disabled member hides another
           Product: gcc
           Version: 8.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: csaba_22 at yahoo dot co.uk
  Target Milestone: ---

The following program is compiled successfully by clang-4.0, clang-6.0,
clang-trunk, GCC 7.3  (Ubuntu 7.3.0-27ubuntu1~18.04) and GCC trunk.

-------------------------------->8--------------------------------------
#include <boost/optional.hpp>
#include <string>

#if __cplusplus > 201402
#include <type_traits>
#else

namespace std {
// This indirection is needed for some older versions of GCC - including 4.8.5
(CWG 1558)
// template<typename...> using __void_t = void; // would be the natural
implementation,
// but the standard did not specify the treatment of unused arguments in an
alias template specializations,
// and GCC chose to ignore them, which makes the natural implementation
unusable.
template<typename...>
struct voider { using type = void; };

// std::void_t will be part of C++17, but until then define it ourselves:
template<typename... T>
using void_t = typename voider<T...>::type;
// void_t is "just a fancy way to spell void" (Walter E Brown)
// But *ALL* the types have to be *well formed* (that's the magic).

}

#endif

namespace detail {
  // check if a type is boost::optional
  template<typename T, typename = void>
  struct is_boost_optional_impl : std::false_type{};

  template<typename T>
  struct is_boost_optional_impl<
    T,
    std::void_t<decltype(std::declval<T>().is_initialized())>>
   : std::true_type {};
}

namespace rj_hlp {

template<typename T>
struct is_boost_optional : detail::is_boost_optional_impl<T>::type {};

}

struct get_from {
    template<
        typename GetWhat,
        typename = typename
std::enable_if<!rj_hlp::is_boost_optional<GetWhat>::value>::type>
    explicit operator GetWhat() const
    {
        return GetWhat{};
    }

    template<typename GetWhat>
    explicit operator boost::optional<GetWhat> const () const
    {
        return boost::make_optional(GetWhat{});
    }

        template <typename GetWhat>
        explicit operator boost::optional<GetWhat> () const
        {
                return this->operator boost::optional<GetWhat> const ();
        }


        template <typename AsWhat>
        AsWhat as() const
        {
                return this->operator AsWhat();
        }
};

struct R {
        boost::optional<std::string> password;

        R()
        : password{ get_from().as<decltype(password)>() }
        {}
};

int main()
{
        R r;
}
-------------------------------->8--------------------------------------

GNU C++11 (GCC) version 8.2.0 (x86_64-pc-linux-gnu)
        compiled by GNU C version 8.2.0, GMP version 6.1.2, MPFR version 4.0.1,
MPC version 1.1.0, isl version isl-0.19-GMP

reports an error:

$ g++-8.2.0 -v -Wno-class-memaccess -pipe -fsanitize=address
-fno-omit-frame-pointer -ftrapv -std=c++11 -fPIC -g -Wall -pedantic -Wextra
-Wformat=2 -Wshadow -Werror -Wmissing-include-dirs -Wuninitialized
-Wfloat-equal -Wcast-align -Wcast-qual -Wwrite-strings -Wlogical-op -O1
-Wno-error=pragmas -O0 -fstrict-aliasing -c -o bilsett.o bilsett.cc


bilsett.cc: In instantiation of ‘AsWhat get_from::as() const [with AsWhat =
boost::optional<std::__cxx11::basic_string<char> >]’:
bilsett.cc:78:48:   required from here
bilsett.cc:70:32: error: no matching function for call to ‘get_from::operator
boost::optional<std::__cxx11::basic_string<char> >() const’
   return this->operator AsWhat();
                                ^
bilsett.cc:49:14: note: candidate: ‘template<class GetWhat, class>
get_from::operator GetWhat() const’
     explicit operator GetWhat() const
              ^~~~~~~~
bilsett.cc:49:14: note:   template argument deduction/substitution failed:
bilsett.cc:48:9: error: no type named ‘type’ in ‘struct std::enable_if<false,
void>’
         typename = typename
std::enable_if<!rj_hlp::is_boost_optional<GetWhat>::value>::type>
         ^~~~~~~~

It looks as if the disabled operator GetWhat on line 49 also prevents the
compiler from using the operator GetWhat on line 55.

Boost is version 1.65.1.0ubuntu1

Reply via email to