3

What is wrong with this code? I thought I could convert due to this answer:

Is it safe to "upcast" a method pointer and use it with base class pointer?

struct B
{
  void f(){}
};

struct D : B
{
  virtual ~D(){}
};

template <typename FP, FP fp>
void g()
{
}

int main()
{
  g<void (D::*)(), &B::f>();
  return 0;
}

Error:

t.cpp:18:27: error: could not convert template argument '&B::f' to 'void (D::*)()'
   g<void (D::*)(), &B::f>();

This doesn't work either:

g<void (D::*)(), static_cast<void (D::*)()>(&B::f)>();
Community
  • 1
  • 1
user1095108
  • 14,119
  • 9
  • 58
  • 116

1 Answers1

4

This is disallowed by the standard (C++11, [temp.arg.nontype]§5):

The following conversions are performed on each expression used as a non-type template-argument. If a non-type template-argument cannot be converted to the type of the corresponding template-parameter then the program is ill-formed.

...

  • For a non-type template-parameter of type pointer to member function, if the template-argument is of type std::nullptr_t, the null member pointer conversion (4.11) is applied; otherwise, no conversions apply. If the template-argument represents a set of overloaded member functions, the matching member function is selected from the set (13.4).

(Emphasis mine)

Casts are not allowed either, because of [temp.arg.nontype]§1:

A template-argument for a non-type, non-template template-parameter shall be one of:

...

  • a pointer to member expressed as described in 5.3.1.

Where 5.3.1§4 reads:

A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses.

This combines to say that a cast experssion is not allowed as a non-type template argument.

So, while such conversions are possible at runtime, it seems there's no way to use them as template arguments.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455