Reputation: 1678
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
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 returningT
” is adjusted to be of type “pointer toT
” or “pointer to function returningT
”, 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