문제

The following code does not compile and I don't know why:

#include <type_traits>

// Base class definition
template<template<typename> class CRTP, typename T> class Base
{
    // Friend function declaration
    public:
        template<template<typename> class CRTP0, typename T0, class>
        friend int func(const Base<CRTP0, T0>& rhs);

    // Protected test variable
    protected:
         int n;
};

// Friend function definition
template<template<typename> class CRTP0, typename T0,
class = typename std::enable_if<true>::type>
int func(const Base<CRTP0, T0>& rhs)
{
    return rhs.n;
}

// Derived class definition
template<typename T> class Derived : public Base<Derived, T> {};

// Main
int main()
{
    Derived<int> x;
    func(x);
    return 0;
}

GCC 4.6.2 (and GCC 4.7.1 on LWS) tells me that :

error: 'int Base<Derived, int>::n' is protected

Meaning that basically, the friendship is not correctly detected. As this is just an extract of my code, I would like to put the definition of the friend function outside of the class definition, like here. So, what is the problem and how to solve it ?

EDIT : I've modified the code to try to isolate the problem and make it far more readable. The current enable_if is always true but for my real code, I will have a "real" condition, here it is just to isolate the problem.

EDIT2 : The liveworkspace is here : friend function problem

도움이 되었습니까?

해결책

I had similar problems with gcc. I think this is a compiler bug: Because your function template has three template parameters rather than the two in the friend declaration, it doesn't match them. In order for your intentions to work correctly with gcc, you must match the friend declaration exactly. This is most easily achieved by using the SFINAE on the function return type

 // Friend function definition
 template<template<typename> class CRTP0, typename T0>
 typename std::enable_if<true,int>::type
 func(const Base<CRTP0, T0>& rhs)
 {
    return rhs.n;
 }

다른 팁

If you try to call func explicitly:

func<Derived, int, void>(x);

g++ complains with:

source.cpp:31:31: error: call of overloaded 'func(Derived<int>&)' is ambiguous
source.cpp:31:31: note: candidates are:
source.cpp:19:5: note: int func(const Base<CRTP0, T0>&) [with CRTP0 = Derived; T0 = int; <template-parameter-1-3> = void]
source.cpp:9:20: note: int func(const Base<CRTP0, T0>&) [with CRTP0 = Derived; T0 = int; <template-parameter-2-3> = void; CRTP = Derived; T = int]

I believe the problem is that the friend declaration is not being correctly identified with the function definition; instead another function template is being declared. This happens even if the class and function templates are predeclared.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top