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

つまり、基本的に、友情は正しく検出されません。これは私のコードの抜粋にすぎないので、ここのように、friend関数の定義をクラス定義の外に置きたいと思います。それで、問題は何ですか、そしてそれをどのように解決するのですか?

編集:問題を切り分けてはるかに読みやすくするためにコードを変更しました。現在のenable_ifは常にtrueですが、私の実際のコードでは、「実際の」状態になります。ここでは、問題を切り分けるだけです。

EDIT2:liveworkspaceはここにあります:友人機能の問題

4

2 に答える 2

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 に答える
0

gccでも同様の問題がありました。これはコンパイラのバグだと思います。関数テンプレートには、friend宣言の2つではなく3つのテンプレートパラメータがあるため、それらと一致しません。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 に答える