Created on 2003-11-13.00:00:00 last changed 18 months ago
CWG 2023-06-15
CWG noted that the derived-to-base conversion is also not allowed for arguments for non-type template parameters. Permitting such conversions is an extension, not a defect.
Additional notes (February, 2023)
Even the following simple case fails on all major implementations:
struct B { void f(); }; struct D : B {}; template<void (D::*)()> int g(); int x = g<&D::f>();
Subclause 7.7 [expr.const] paragraph 12 is unambiguous that the code is ill-formed, but that seems unfortunate.
None of my compilers accept this, which surprised me a little. Is the base-to-derived member function conversion considered to be a runtime-only thing?
template <class D> struct B { template <class X> void f(X) {} template <class X, void (D::*)(X) = &B<D>::f<X> > struct row {}; }; struct D : B<D> { void g(int); row<int,&D::g> r1; row<char*> r2; };
John Spicer: This is not among the permitted conversions listed in 14.3.
I'm not sure there is a terribly good reason for that. Some of the template argument rules for external entities were made conservatively because of concerns about issues of mangling template argument names.
David Abrahams: I'd really like to see that restriction loosened. It is a serious inconvenience because there appears to be no way to supply a usable default in this case. Zero would be an OK default if I could use the function pointer's equality to zero as a compile-time switch to choose an empty function implementation:
template <bool x> struct tag {}; template <class D> struct B { template <class X> void f(X) {} template <class X, void (D::*pmf)(X) = 0 > struct row { void h() { h(tag<(pmf == 0)>(), pmf); } void h(tag<1>, ...) {} void h(tag<0>, void (D::*q)(X)) { /*something*/} }; }; struct D : B<D> { void g(int); row<int,&D::g> r1; row<char*> r2; };
But there appears to be no way to get that effect either. The result is that you end up doing something like:
template <class X, void (D::*pmf)(X) = 0 > struct row { void h() { if (pmf) /*something*/ } };
which invariably makes compilers warn that you're switching on a constant expression.
History | |||
---|---|---|---|
Date | User | Action | Args |
2023-06-15 19:09:35 | admin | set | messages: + msg7321 |
2023-06-15 19:09:35 | admin | set | status: open -> nad |
2023-02-12 17:30:17 | admin | set | messages: + msg7198 |
2003-11-13 00:00:00 | admin | create |