以下代码无法编译,我不知道原因:
#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
答案 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;
}