Mikhail Maltsev
Mikhail Maltsev

Reputation: 1678

Defining out-of-line member template functions

Consider this (minimized) example:

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 ();
};

I defined a class template which has template member functions with non-type parameters. Note that Callback depends on value_type typedef. Now I want to define the functions themselves:

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 () {}

I get inconsistent errors from the compilers. The result does not depend on options, specifying the version of C++ standard (i.e., same for C++98, C++11 and C++14), but depends on the compiler.

GCC 6.0.0 (recent trunk, as well as several other versions) accepts this code.

Clang 3.7.0 (recent trunk) gives the following error:

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 (Intel C++ Compiler v. 15.0.3) gives two errors:

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)

What is the expected behavior (according to the standard)? If the code is wrong, how do I fix the function definitions?

Upvotes: 9

Views: 1352

Answers (1)

Barry
Barry

Reputation: 304007

Your code looks fine to me, I see no reason for it to not compile. Probably a bug on the compilers that disallow it. However, since [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.

You could simply switch Callback yourself to be a pointer-to-function. The behavior would be identical in all respects, with the added benefit that this code also compiles on clang.

Upvotes: 1

Related Questions