Title
Virtual overriding by template member function specializations
Status
nad
Section
13.7.3 [temp.mem]
Submitter
Bill Gibbons

Created on 1999-05-07.00:00:00 last changed 255 months ago

Messages

Date: 2003-04-15.00:00:00

Notes from April 2003 meeting:

This was discussed again, and the consensus was that we did not want to make a change, and in particular we did not want to make it an error and risk breaking existing code.

Date: 2003-04-15.00:00:00

Notes from April 2003 meeting:

This was discussed again, and the consensus was that we did not want to make a change, and in particular we did not want to make it an error and risk breaking existing code.

Date: 2002-10-15.00:00:00

Notes from October 2002 meeting:

This was reopened because of a discussion while reviewing possible extensions.

Date: 2022-02-18.07:47:23

According to 13.7.3 [temp.mem] paragraph 4,

A specialization of a member function template does not override a virtual function from a base class.
Bill Gibbons: I think that's sufficiently surprising behavior that it should be ill-formed instead.

As I recall, the main reason why a member function template cannot be virtual is that you can't easily construct reasonable vtables for an infinite set of functions. That doesn't apply to overrides.

Another problem is that you don't know that a specialization overrides until the specialization exists:

    struct A {
        virtual void f(int);
    };
    struct B : A {
        template<class T> void f(T);  // does this override?
    };
But this could be handled by saying:
  • If deduction using the type of an overridable function in a base class succeeds, the template is implicitly specialized to provide the override.
  • If this yields more than one override for a function, the program is ill-formed.
  • If a specialization due to explicit template arguments creates an override that did not previously exist, the program is ill-formed. (Or alternatively, it is not an override.)
The last case might only involve non-deducible contexts, e.g.
    template<int I> struct X;
    struct A {
        virtual void f(A<5>);
    };
    struct B : A {
        template<int I, int J> void f(A<I+J>);  // does not overrride
    };

    void g(B *b) {
        X<t> x;
        b->f<3,2>(x);  // specialization B::f(A<5>) makes program ill-formed
    }
So I think there are reasonable semantics. But is it useful?

If not, I think the creation of a specialization that would have been an override had it been declared in the class should be an error.

Daveed Vandevoorde: There is real code out there that is written with this rule in mind. Changing the standard on them would not be good form, IMO.

Mike Ball: Also, if you allow template functions to be specialized outside of the class you introduce yet another non-obvious ordering constraint.

Please don't make such a change after the fact.

John Spicer: This is the result of an explicit committee decision. The reason for this rule is that it is too easy to unwittingly override a function from a base class, which was probably not what was intended when the template was written. Overriding should be a conscious decision by the class writer, not something done accidentally by a template.

Rationale (10/99): The Standard correctly reflects the intent of the Committee.

History
Date User Action Args
2003-04-25 00:00:00adminsetmessages: + msg881
2003-04-25 00:00:00adminsetstatus: open -> nad
2002-11-08 00:00:00adminsetmessages: + msg764
2002-11-08 00:00:00adminsetstatus: nad -> open
2000-02-23 00:00:00adminsetmessages: + msg291
2000-02-23 00:00:00adminsetstatus: open -> nad
1999-05-07 00:00:00admincreate