3

以下代码无法编译,我不知道为什么:

#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(和 LWS 上的 GCC 4.7.1)告诉我:

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

这意味着基本上没有正确检测到友谊。由于这只是我的代码的摘录,我想将友元函数的定义放在类定义之外,就像这里一样。那么,问题是什么以及如何解决呢?

编辑:我已经修改了代码以尝试隔离问题并使其更具可读性。当前的 enable_if 始终为真,但对于我的真实代码,我将有一个“真实”条件,这里只是为了隔离问题。

EDIT2:liveworkspace 在这里:朋友功能问题

4

2 回答 2

0

我对 gcc 也有类似的问题。我认为这是一个编译器错误:因为您的函数模板具有三个模板参数,而不是朋友声明中的两个,所以它不匹配它们。为了使您的意图正确地使用 gcc,您必须完全匹配朋友声明。这很容易通过在函数返回类型上使用 SFINAE 来实现

 // 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;
 }
于 2012-08-19T18:47:02.920 回答
0

如果您尝试func显式调用:

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

g++ 抱怨:

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]

我认为问题在于friend声明没有被函数定义正确识别;相反,正在声明另一个函数模板。即使预先声明了类和函数模板,也会发生这种情况。

于 2012-08-19T15:41:54.993 回答