问题
Why does the following code fail to compile? Even though it is legal to do void* ptr = 0;
template <void* ptr = 0>
void func();
int main() {
func();
return 0;
}
I ask because I found that a very trusted source did something similar and it failed to compile on my machine
NOTE Should have posted the compiler error along with my question so here it is
so_test.cpp:1:23: error: null non-type template argument must be cast to template parameter type 'void *'
template <void* ptr = 0>
^
static_cast<void *>( )
so_test.cpp:1:17: note: template parameter is declared here
template <void* ptr = 0>
^
so_test.cpp:5:5: error: no matching function for call to 'func'
func();
^~~~
so_test.cpp:2:6: note: candidate template ignored: substitution failure [with ptr = nullptr]: null non-type template argument must be cast to template parameter type 'void *'
void func();
^
回答1:
Template parameters of type void*
are not allowed. See [temp.param]/4 in the standard, also summarized at http://en.cppreference.com/w/cpp/language/template_parameters#Non-type_template_parameter
A non-type template-parameter shall have one of the following (optionally cv-qualified) types:
- integral or enumeration type,
- pointer to object or pointer to function,
- lvalue reference to object or lvalue reference to function,
- pointer to member,
std::nullptr_t
.
Since void
is not an object or function type, void*
is not among the permitted types.
Addendum: A void*
value known at compile time wouldn't be very useful. It's not possible to examine its value at compile time since reinterpret_cast
is not allowed in constant expressions; nor is it possible to convert it to T*
for some object type T
at compile time.
回答2:
You tried to initialize a pointer with an int
. Many implicit conversions, including integer-to-pointer conversions, don't happen in non-type template parameters.
The cppreference summary of the behaviour in C++14 for non-template parameters of pointer to object type is:
For pointers to objects, the template arguments have to designate the address of an object with static storage duration and a linkage (either internal or external), or a constant expression that evaluates to the appropriate null pointer or std::nullptr_t value.
So the code could be:
template <void* ptr = nullptr>
void f();
Footnote: it seems unclear whether void *
is allowed as a parameter type, but compilers accept the above code.
来源:https://stackoverflow.com/questions/38154762/why-using-0-as-default-non-type-template-parameter-for-void-is-not-allowed