定义外联成员模板函数

Defining out-of-line member template functions

考虑这个(最小化的)示例:

template <typename Descriptor>
class hash_table
{
public:
  typedef int value_type;

  template <typename Argument, int Callback (value_type *, Argument)>
  void traverse (Argument);

  template <int Callback (value_type *)>
  void traverse_void ();
};

我定义了一个 class 模板,其中包含带有非类型参数的模板成员函数。请注意 Callback 取决于 value_type typedef。现在我想自己定义函数:

template <typename Descriptor>
template <typename Argument, int Callback (typename hash_table <Descriptor>::value_type *, Argument)>
void hash_table <Descriptor>::traverse (Argument) {}

template <typename Descriptor>
template <int Callback (typename hash_table <Descriptor>::value_type *)>
void hash_table <Descriptor>::traverse_void () {}

我从编译器中得到不一致的错误。结果不依赖于选项,指定 C++ 标准的版本(即,与 C++98、C++11 和 C++14 相同),但取决于编译器。

GCC 6.0.0(最近的主干,以及其他几个版本)接受此代码。

Clang 3.7.0(最近的主干)给出以下错误:

test.cc:18:31: error: out-of-line definition of 'traverse_void' does not match any declaration in 'hash_table<Descriptor>'
void hash_table <Descriptor>::traverse_void() {}
                              ^~~~~~~~~~~~~
1 error generated.

EDG(英特尔 C++ 编译器 v.15.0.3)给出了两个错误:

test.cc(15): error: declaration is incompatible with function template "void hash_table<Descriptor>::traverse<Argument,Callback>(Argument)" (declared at line 7)
  void hash_table <Descriptor>::traverse (Argument) {}
                                ^

test.cc(19): error: declaration is incompatible with function template "void hash_table<Descriptor>::traverse_void<Callback>()" (declared at line 10)
  void hash_table <Descriptor>::traverse_void () {}
                                ^
compilation aborted for test.cc (code 2)

预期的行为是什么(根据标准)?如果代码错误,我该如何修改函数定义?

我觉得你的代码很好,我看不出有什么理由不编译。可能是不允许它的编译器上的错误。但是,由于 [temp.param]:

A non-type template-parameter of type “array of T” or “function returning T” is adjusted to be of type “pointer to T” or “pointer to function returning T”, respectively.

您可以简单地将 Callback 自己切换为指向函数的指针。行为在所有方面都是相同的,额外的好处是这段代码也可以在 clang 上编译。