使用CRTP + enable_if的朋友功能不起作用?

时间:2012-08-19 14:02:35

标签: c++ templates c++11 variadic-templates crtp

以下代码无法编译,我不知道原因:

#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始终为true,但对于我的实际代码,我将有一个“真实”的条件,这里只是为了隔离问题。

EDIT2:liveworkspace在这里:friend function problem

2 个答案:

答案 0 :(得分: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声明未被函数定义正确识别;而是宣布另一个功能模板。即使类和函数模板是预先声明的,也会发生这种情况。

答案 1 :(得分: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;
 }