[Bug c++/89151] New: SFINAE-disabled member hides another

csaba_22 at yahoo dot co.uk gcc-bugzilla@gcc.gnu.org
Fri Feb 1 17:00:00 GMT 2019


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


More information about the Gcc-bugs mailing list