1

In the following snippet, I have a template function foo() that takes a pointer to some object as a template argument.

class P {};
class Q : public P {};

P p;
Q q;

template <P*> void foo() {}

void test() {
  foo<&p>();
  foo<&q>();
}

According to the documentation, this should work provided that

For pointers to objects, the template arguments have to designate the address of a complete 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.

Since the object in question must have static storage duration, I define it globally. However, the compiler complains about the second invocation of foo():

test.cc:66:7: error: no matching function for call to 'foo'
      foo<&q>();
      ^~~~~~~
test.cc:62:26: note: candidate template ignored: invalid
explicitly-specified argument for template parameter 'p'
    template <P* p> void foo() {}

I don't understand why is this happening, and why such usage is forbidden?

Pasha
  • 6,298
  • 2
  • 22
  • 34
  • 1
    this answer [here](https://stackoverflow.com/questions/4027154/why-cant-i-downcast-pointer-to-members-in-template-arguments) may offer some insight: *"for a non-type template-parameter of type pointer to object, qualification conversions (4.4) and the array-to-pointer conversion (4.2) are applied"*. Nothing is said about base-class conversions... – kmdreko Aug 07 '18 at 02:12

1 Answers1

6

the template arguments have to designate the address of a complete object with static storage duration

A base class subobject is not a complete object.

T.C.
  • 133,968
  • 17
  • 288
  • 421