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

            Bug ID: 96204
           Summary: gcc complains about private member access in SFINAE
                    context
           Product: gcc
           Version: 10.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lts-rudolph at gmx dot de
  Target Milestone: ---

gcc complains with following error in the example code:

main.cpp:59:72: error: 'void Child::setAttr(int)' is private within this
context
   59 | struct has_set_attr_method<T,
void_t<decltype(std::declval<T>().setAttr(1))>> {
      |                                              
~~~~~~~~~~~~~~~~~~~~~~~~~^~~
main.cpp:85:14: note: declared private here
   85 |         void setAttr(int x) {
      |              ^~~~~~~
main.cpp:59:72: error: 'void Child::setAttr(int)' is private within this
context
   59 | struct has_set_attr_method<T,
void_t<decltype(std::declval<T>().setAttr(1))>> {
      |                                              
~~~~~~~~~~~~~~~~~~~~~~~~~^~~
main.cpp:85:14: note: declared private here
   85 |         void setAttr(int x) {
      |              ^~~~~~~
main.cpp:59:72: error: 'void Child::setAttr(int)' is private within this
context
   59 | struct has_set_attr_method<T,
void_t<decltype(std::declval<T>().setAttr(1))>> {
      |                                              
~~~~~~~~~~~~~~~~~~~~~~~~~^~~
main.cpp:85:14: note: declared private here
   85 |         void setAttr(int x) {


Full code example:

---------------
template <typename, typename = void_t<>>
struct has_set_attr_method {
    static constexpr bool value = false;
};
template <typename T>
struct has_set_attr_method<T, void_t<decltype(std::declval<T>().setAttr(1))>> {
    static constexpr bool value = true;
};

struct Parent
{
    public:
        template<typename T>
            static void create()    {   
                auto obj = T::create();
                if constexpr(has_set_attr_method<T>::value) {
                    cout << "has setAttr" << endl;
                } else {
                    cout << "no setAttr" << endl;
                }
            }
};

struct Child : public Parent {
    public:
        friend class Parent;
        static auto create() {
            return Child();
        }

    private:
        void setAttr(int x) {
        }
};

int main(int argc, char const *argv[]) {
    Parent::create<Child>();
    return 0;
}

---------------

Interestingly the failure depends on "friend" declaration inside "Child".

Reply via email to