http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58954

            Bug ID: 58954
           Summary: accessing a private member function in decltype of a
                    friend class causes access control error
           Product: gcc
           Version: 4.8.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: myspam456 at gmail dot com

When trying to use decltype on a member function which has a late specified
return type calling a private member function of a friend class I receive the
below error.  My understanding is that the "friend struct base<derived>;" in
derived should cause this error to not occur which is the case with clang.  

Adding "foo_argument<derived>" does cause the error to disappear.  

I apologize for the length of the example, but I've had difficulty reproducing
it with fewer lines of code.

main.cpp: In instantiation of ‘struct foo_argument<derived>’:
main.cpp:43:47:   required from here
main.cpp:9:50: error: no matching function for call to
‘foo_argument<derived>::test(<unresolved overloaded function type>)’
     using type = decltype(test(&T::template foo<>));
                                                  ^
main.cpp:9:50: note: candidate is:
main.cpp:7:16: note: template<class Ret, class C, class Arg> static Arg
foo_argument<T>::test(Ret (C::*)(Arg)) [with Ret = Ret; C = C; Arg = Arg; T =
derived]
     static Arg test(Ret (C::*)(Arg));
                ^
main.cpp:7:16: note:   template argument deduction/substitution failed:
main.cpp:35:9: error: ‘int derived::foo_impl(int)’ is private
     int foo_impl(int i)
         ^
main.cpp:9:50: error: within this context
     using type = decltype(test(&T::template foo<>));

The below example can be seen at:
http://coliru.stacked-crooked.com/a/3ffd6557434a3ab9

#include <utility>

template<class T>
struct foo_argument
{
    template<class Ret, class C, class Arg>
    static Arg test(Ret (C::*)(Arg));

    using type = decltype(test(&T::template foo<>));
};

template<class T, class D>
struct dependent { typedef T type; };

template<class T, class D>
using Dependent = typename dependent<T, D>::type;

template<class T>
struct base
{
    friend struct foo_argument<T>;

    template<class Ignore = void>
    auto foo(int i) -> decltype(std::declval<Dependent<T&,
Ignore>>().foo_impl(i))
    {
        return static_cast<T&>(*this).foo_impl(i);
    }
};

struct derived : base<derived>
{
    friend struct base<derived>;
    //friend struct foo_argument<derived>;
  private:
    int foo_impl(int i)
    {
        return 123 + i;
    }
};

int main()
{
    using foo_arg_type = foo_argument<derived>::type;
}

Reply via email to