Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 具有CRTP+的友元函数;如果不工作,是否启用_?_C++_Templates_C++11_Variadic Templates_Crtp - Fatal编程技术网

C++ 具有CRTP+的友元函数;如果不工作,是否启用_?

C++ 具有CRTP+的友元函数;如果不工作,是否启用_?,c++,templates,c++11,variadic-templates,crtp,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 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;
}
#包括
//基类定义
模板类基
{
//友元函数声明
公众:
模板
friend int func(常数基和rhs);
//受保护测试变量
受保护的:
int n;
};
//友元函数定义
模板
int func(常数基和rhs)
{
返回rhs.n;
}
//派生类定义
派生的模板类:公共基{};
//主要
int main()
{
导出x;
func(x);
返回0;
}
GCC 4.6.2(以及LWS上的GCC 4.7.1)告诉我:

error: 'int Base<Derived, int>::n' is protected
错误:“int Base::n”受保护
也就是说,基本上,友谊没有被正确地检测到。因为这只是我代码的一个摘录,所以我想把friend函数的定义放在类定义之外,就像这里一样。那么,问题是什么?如何解决

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


EDIT2:liveworkspace在这里:

如果您尝试显式调用
func

func<Derived, int, void>(x);
func(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]
source.cpp:31:31:错误:重载“func(派生&)”的调用不明确
资料来源:cpp:31:31:注:候选人为:
source.cpp:19:5:注意:int func(const Base&)[带CRTP0=Derived;T0=int;=void]
source.cpp:9:20:注意:int func(const Base&)[带CRTP0=Derived;T0=int;=void;CRTP=Derived;T=int]

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

我在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;
 }
//友元函数定义
模板
typename std::enable_if::type
func(常数基和rhs)
{
返回rhs.n;
}

我希望这段代码只是为了好玩而写的,即使有人纠正它,也不会在任何地方使用:)当然,这只是一段测试代码,但我有一段基于这种不可读语法的真实代码…;-)在我看来,这好像是个bug,你能用clang测试一下吗?是的,clang++编译时没有任何错误。这里报告了这个bug: