Re: Instantiation of virtual member functions of class templates
Nikolay Ivchenkov wrote:
Given the following example:
#include <iostream>
struct B
{
virtual void f() const = 0;
};
template <class T>
struct D : B
{
// overrides B::f
virtual void f() const
{
T()();
}
};
struct F
{
void operator ()() const
{
std::cout << "F::operator()\n";
}
};
int main()
{
D<F> d;
B &b = d;
b.f(); // statically refers to B::f
// dynamically calls D<F>::f
}
is there normative rules that require D<F>::f to be implicitly
instantiated?
Yes, at 3.2p2:
A virtual member function is odr-used if it is not pure.
And 14.7.1p1:
Unless a member of a class template or a member template
has been explicitly instantiated or explicitly specialized,
the specialization of the member is implicitly instantiated
when the specialization is referenced in a context that requires
the member definition to exist;
Another thing is relevant for virtual functions. In this case, pure
virtuals. Consider:
template<typename T>
struct B {
typedef int type;
virtual void f() = 0;
};
B<int>::type global;
There is IMO a defect for pure virtual member functions of class templates,
which I reported earlier, but which was somehow lost in the amount of posts
and not discussed in an issue report. I want to report it in more details
now. At 14.7.1p9
It is unspecified whether or not an implementation implicitly
instantiates a virtual member function of a class template if
the virtual member function would not otherwise be instantiated.
With core issue #1096 being reinstated, this effectively allows an
implementation to require a definition of the pure virtual. There sometimes
may be an ambiguity between whether saying "instantiated a member function"
means to instantiate definition or to merely instantiate a declaration. In
this case there is no such ambiguity. We know that this text talks about
instantiating definitions (as does #1096), because declarations must be
instantiated anyway, no matter what you do:
template<typename T>
struct A {
virtual void f(typename T::type) = 0;
};
// declaration of f is instantiated now. This
// must result in a diagnostic *now*!
A<int> a;
The sentence would not make any sense if it merely talked about
instantiating declarations. So, assuming we fix this sentence, and only
talk
about non-pure virtual member functions. But the ODR already tells us (as
quoted above) that any non-pure virtual function is odr-used, and that odr-
used functions must be defined. So I'm not even sure whether we need the
above sentence at all. Transforming it into a note seems costumary
[Note: A non-pure virtual member function is always odr-used even if
not explicitly referenced by the program].
There was argued to be some weasel wording at 10.4p2. But I think it has no
effect on this:
A pure virtual function need be defined only if called with, or as if
with (12.4), the qualified-id syntax (5.1).
I think this is redundant if we assume resolution of issue #1174 and should
be a note: The ODR already states that the function is odr-used if
referenced with a qualified name in a potentially evaluated expression and
selected by OR or if the function is a destructor under the conditions of
12.4, which are the two cases catched by 10.4p2.
But more importantly, whether or not the function needs to be defined is
totally unimportant for the rule about implicit instatiations to take
place.
If the function needs to be defined, 14.7.1p1 requires us to instantiate
it,
which will in the end require a definition. If the function needs *not* be
defined, then 14.7.1p9 still allows us to implicitly instantiate it. It
explicitly ends with
... if the virtual member function would not otherwise be instantiated.
You can argue that 14p8 requires a definition of the member function of the
class template, but that that definition is not really required because
10.4p2 allows it to be omitted. But I don't think we can argue that way.
10.4p2 allows the definition of a pure virtual member function to be
omitted, but it does not talk about member definitions of class templates
which I think are intended to mean different things here. Arguably we have
some weasel going on, but I think the situation is still clear by
comparison. If you argue that way, you will require the following to be
well-formed too:
template<typename T>
struct A { virtual void f() = 0; };
// 10.4p2 wouldn't really require A<T>::f to be defined.
template void A<int>::f();
But this is ill-formed for the same reason the implicit instantiation of
"f"
is ill-formed: There is no definition of the member of the class template,
so the explicit instantiation of the class member definition fails (as
required by 14.7.2p5). In other words, it wants to instantiate the
definition of the class member A<int>::f, for which the definition of the
class template member A<T>::f is required.
Someone once said the Standard doesn't express what it could be interpreted
to, but what it most probably does. I think in this case it most probably
expresses that implementations are allowed to require the definition of
pure
virtual member functions of class templates. Therefor, I think we have a
defect in paragraph 14.7.1p9, which can be solved by transforming the
quoted
part into a note.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]