I figured an explicit instantiation request would automatically instantiate all base class members also, but I get a linker error: unresolved external symbol "public: void Base<int>::foo(int)" when building this code using Visual Studio 2008 or 2010.
Note that adding a call to foo() inside bar() forces the compiler to instantiate Base<int>::bar() and the build succeeds, so it appears that the compiler has all the necessary information to instantiate foo().
Obviously, explicitly instantiating Base<int> in source.cpp allows the build to succeed, but it seems silly to need to explicitly instantiate any dependent base classes whenever explicitly instantiating a derived class.
Is this normal? I couldn't find what the standard says regarding this issue.
header.h
template<typename T>
class Base {
public:
void foo();
};
template<typename T>
class Derived : public Base<T> {
public:
void bar();
};
source.cpp
#include "header.h"
template<typename T>
void Base<T>::foo() { }
template<typename T>
void Derived<T>::bar() {
// this->foo(); // adding this forces instantiation of foo()???
}
template class Derived<int>;
main.cpp
#include "header.h"
int main() {
Derived<int> d;
d.foo(); // Linker Error: unresolved external symbol "public: void Base<int>::foo(int)"
}
Edit:
It looks like the Standard says only members of a class get instantiated by an explicit class instantiation, so the linker error is justified in my example.
Note that a class is defined by class-head { member-specification } and "The member-specification in a class definition declares the full set of members of the class; no member can be added elsewhere." So members are only between the curly braces { }, and public base class members don't become members of the derived class, they are merely accessible from the derived class or by objects of the derived class.
My only remaining question is why the Standard specifies that explicit instantiation of a class template only instantiates members and not members of base classes? My guess is that this allows greater control of what gets explicitly instantiated where. Someone that's using explicit template class instantiations would most likely have the base class definitions in a different file than the derived class definitions, and would explicitly instantiate each separately.
The Standard says
The explicit instantiation of a class template specialization implies the instantiation of all of its members not previously explicitly specialized in the translation unit containing the explicit instantiation.
In other words, it does not mandate that base classes are explicitly instantiated in turn. It will cause an implicit instantiation of them which will not instantiate their member definitions up-front. It's some ugly glitch in the Standard as to whether some text when it says "member" means "direct" or "inherited" member, as that often seems to be "obvious" to the one who wrote the Standards wording, but not to the one who reads it. C++0x has added some clarifications (it also has a difference between explicit instantiation declarations and definitions that C++03 doesn't have, but even ignoring that, the C++0x wording contains some more bits of insight):
An explicit instantiation that names a class template specialization is also an explicit instantiation of the
same kind (declaration or definition) of each of its members (not including members inherited from base
classes) that has not been previously explicitly specialized in the translation unit containing the explicit
instantiation, except as described below. [ Note: In addition, it will typically be an explicit instantiation of
certain implementation-dependent data about the class. — end note ]
Related
I have the following scheme:
struct Baz {};
struct Qux {};
struct Base {
virtual ~Base() {}
virtual void foo() = 0;
};
template<typename T> struct Identity { static bool const value = false; };
template<typename T> void bar(T) { static_assert(Identity<T>::value, "Busted!!!"); }
template<> void bar<Baz>(Baz) {}
template<typename T>
struct Derived : Base {
T m;
void foo() { bar(m); }
};
int main() {
Base *b0 = new Derived<Baz>;
b0->foo();
Base *b1 = new Derived<Qux>;
(void) b1;
}
That is, I have a pure virtual class Base and a template class Derived that inherits from Base and overrides the pure virtual function foo as required. Now, inside foo I call function template bar. bar has a specialization for class Baz but not for class Qux. When in main I'm trying to materialize an object of Derived<Baz> everything's OK. But when I try to materialize an object of Derived<Qux> compiler hits static_assert.
Q:
Is there a way to transform my code in such a way that compiler will hit static assert in Derived<Qux> only if Derived<Qux>::foo() is called.
That is, materializing an object of Derived<Qux> will pass:
Base *b1 = new Derived<Qux>;
But when later in code the programmer tries to call:
b1->foo(); // compile error static assert
The standard says an interesting thing at [temp.inst]/9:
An implementation shall not implicitly instantiate a function
template, a variable template, a member template, a non-virtual member
function, a member class, a static data member of a class template, or
a substatement of a constexpr if statement, unless such instantiation
is required. 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.
The decision of instantiating a virtual function is up to the implementation, but only if it is not needed otherwise. The question we are faced with is therefore: when is the definition needed according to the standard itself?
The answer is at [class.virtual]/11 and [temp.inst]/2:
A virtual function declared in a class shall be defined, or declared pure in that class, or both; no diagnostic is required
The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or noexcept-specifiers of the class member functions
So any instantiation of the class template, will instantiate a declaration of Derived::foo, which by a chain reaction requires a definition. So the definition must be instantiated too, if it is available.
The only way an implementation can exercise the leeway it is given in the first quoted paragraph, is if Derived::foo is pure virtual too. As an example, both Clang and GCC do just that. That of course is likely to be of limited help to you.
So to make a long story short, it's a no-starter, so long as the function is virtual (and not pure virtual).
#StoryTeller gives a detailed answer referencing the spec, etc. but I'm going to push back on your question and ask what you are really trying to do. As the question is written, it is dead obvious the answer is "no" because you are asking for a compile time error on something that is only determinable at runtime. E.g.:
Base *b;
if (user_input() == 42) {
b = new Derived<Baz>();
} else {
b = new Derived<Qux>();
}
b->foo();
Do you want a compiler error for this case? If so you'll need to define the conditions under which you think Qux::foo should be considered to be "called." At present the compiler is assuming a method defined as virtual in an instantiated class is called. Clearly you want something less conservative, but what?
If you have more specific compile time type information, it may be possible to catch the error at runtime. E.g.
Derived<Qux> d = new Derived<Qux>();
d->foo();
If foo is a non-virtual templated method, it is possible it could validate the base type at compile time and then dispatch to the virtual method. (It will likely require changing the signature of foo to have the type somehow.)
A far better solution would be to break different types of functionality in the interface into different classes and introduce a mechanism to get specific interfaces on a given concrete class. This can be checked at compile time if you have the concretely types class in hand and at runtime if doing a dynamic lookup of an interface.
Unfortunately, I studied class design and design patterns mostly in the context of Java; thus, I sometimes have a hard time to translate a familiar pattern to C++.
Assume we want to have a base class which's functionality is extended by a sub-class. In Java, we would do something like this:
public class BaseClass<T> {
//T is used here
protected int foo = 0;
}
public class DerivedClass<T> extends BaseClass<T> {
public void incr_foo() {
++foo;
}
}
Which I directly translated to C++:
template<class T>
class BaseClass {
protected:
size_t foo = 0;
//T is used here
};
template<class T>
class DerivedClass : public BaseClass<T> {
public:
void incr_foo() {
++(this->foo);
}
};
Since the C++ semantics of 'protected' diver from the Java-semantics, we need to use something like 'this->foo' to access protected members of the base class.
Edit: If we just use '++foo', the compiler gives the error: 'use of undeclared identifier foo'.
EditEnd
If you need to access several members of the base class, this can get a bit tedious and is not so nice to read.
Is this a good design desicion? If not, what better ways are there to achieve this?
This has nothing to do with the member being protected; you'd get the exact same error with a public member.
The real reason is that templates are involed. More specifically, that your class template has a base class which depends on a template parameter. This means that when parsing the template, the compiler will not (be able to) look into that base class to find inherited members which are used unqualified. It makes sense: when the template is parsed, the template parameter values are not known yet and thus the compiler has no idea what members the base class will have (remember partial and total specialisation exist!).
In order to overcome this, you must somehow tell the compiler that the name foo depends on template parameters (that it's a dependent name). Once you do so, the compiler will not try to resolve it when parsing the template; it will postpone resolution until the template is instantiated. At that point, template arguments are known and thus the base class can be checked.
You have three ways to mark a member name as dependent:
Refer to the name through this, as you're doing: this->foo
Refer to the name through base-class qualification: BaseClass<T>::foo
Bring the name into the scope of the derived class:
template<class T>
class DerivedClass : public BaseClass<T> {
protected:
using BaseClass<T>::foo; // from this point on, `foo` is a dependent name
public:
void incr_foo() {
++foo; // works fine now
}
};
BaseClass<T> is a dependent type - it depends on the template parameter used to instantiate DerivedClass. Until DerivedClass instantiated, the compiler doesn't know what the type is: it might be an instantiation of the generic template, or it might be an explicit specialisation, with different members.
So, within the definition of DerivedClass, there is no way to know which names refer to members of the base class. You have to specify that they are, using this-> or BaseClass::.
In a class with a non-dependent base class, you can use any accessible base-class members as if they were direct members, just as in Java.
What is the point of the following using-declarations
using eoPop<MOEOT>::size;
using eoPop<MOEOT>::operator[];
using eoPop<MOEOT>::back;
using eoPop<MOEOT>::pop_back;
Taken from the class defined here. Surely, because eoPop<EOT> inherits std::vector<EOT>, the methods size, operator[] , back and pop_back are public there is no need for the using declaration. Are the using declaration used to force instantiation?
Although I don't know why they've decided to include those using-declarations, I can tell why the code would be ill-formed without them.
But first, repeating from a comment:
A using-declaration doesn't require the existence of the definition the nominated entity (here: it doesn't require the existence of the definition of those functions). Consider:
void foo();
int main()
{
using ::foo; // doesn't require the definition of `foo` to exist
return 0;
}
If a class template gets implicitly instantiated, the declarations of its member functions are instantiated, but not their definitions (as per [temp.inst]/1). The base classes of a class template are also instantiated if said class template is implicitly instantiated (which in turn leads to the instantiation of the declarations of the member functions of those base class templates). Therefore, the using-declaration doesn't help with instantiation.
An effect of those using-declarations is that the names declared are visible for non-dependent name lookup. As per [temp.dep]/3
In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup [...].
In the linked code, we find for example i<size(). The name size here is non-dependent, therefore the base class scope is not searched, and eoPop < MOEOT > :: size would not be found without the using-declaration.
Another reason to use using-declarations is if you want to overload a member function of a base class. If you don't use the using-decl, the member function in the derived class simply hides every overload (with the same name) in the base class. As far as I can see, this is not used in the linked code.
I'm trying to understand if a simple CRTP pattern is valid by the standard.
The code below compiles and works as expected (on clang).
But my understanding of the relevant standard chapters/paragraphs is that
the point of instantiation of the virtual function CRTP< Derived, Base >::DoSomething()
should be at point (B) of the code, where the full declaration of Derived is not available.
Therefore the inner typedef Type should not be available either.
Can anyone kindly point out the relevant standard chapter that validates this code?
In other words, something that says that in this case the virtual function is instantiated
ATFER point C?
Thanks a lot in advance for any insight.
Francesco
//-------------------------
// START CODE
#include <iostream>
struct Type1 {};
struct Type2 {};
struct Base
{
virtual ~Base() {}
virtual void DoSomething() = 0;
};
template< typename T, typename U >
struct CRTP : U
{
virtual void DoSomething() { DoSomething( typename T::Type() ); }
void DoSomething( Type1 ) { std::cout << "1\n"; }
void DoSomething( Type2 ) { std::cout << "2\n"; }
};
// (A) point of inst. of CRTP< Derived, Base > ( 14.7.1.4 ) ??
// (B) point of inst. of CRTP< Derived, Base >::DoSomething() (14.6.4.1.4 ) ??
struct Derived : CRTP< Derived, Base >
{
typedef Type2 Type;
};
// (C)
int main()
{
Base * ptr = new Derived;
ptr->DoSomething();
delete ptr;
}
// END CODE
//-------------------------
Relevant (?) standard paragraphs:
14.6.4.1
4 If a virtual function is implicitly instantiated, its point of instantiation is immediately following the point of instantiation of its enclosing class template specialization.
14.7.1
4 A class template specialization is implicitly instantiated if the class type is used in a context that requires a completely-defined object type or if the completeness of the class type might affect the semantics of the program.
14.7.1
9 An implementation shall not implicitly instantiate a function template, a member template, a non-virtual member function, a member class, or a static data member of a class template that does not require instan- tiation. 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.
This appears to be a result of the compiler delaying instantiation of CRTP<Derived, Base>::DoSomething() until the end of the translation unit, as it is allowed to do (see CWG issue 993).
CRTP<Derived, Base> is definitely instantiated right before the definition of Derived (§14.6.4.1 [temp.point]/p4, all quotes are to N3936):
For a class template specialization, a class member template
specialization, or a specialization for a class member of a class
template, if the specialization is implicitly instantiated because it
is referenced from within another template specialization, if the
context from which the specialization is referenced depends on a
template parameter, and if the specialization is not instantiated
previous to the instantiation of the enclosing template, the point of
instantiation is immediately before the point of instantiation of the
enclosing template. Otherwise, the point of instantiation for such a
specialization immediately precedes the namespace scope declaration or
definition that refers to the specialization.
Whether CRTP<Derived, Base>::DoSomething() is required to be instantiated at all depends on the meaning of the phrase referenced in a context that requires the member definition to exist (§14.7.1 [temp.inst]/p2). All non-pure virtual functions are odr-used (§3.2 [basic.def.odr]/p2), and "every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program" (§3.2 [basic.def.odr]/p4); whether that counts as "referenced in a context that requires the member definition to exist" is unclear.
(Even if it's not required to be instantiated, however, the compiler is still free to instantiate it per §14.7.1 [temp.inst]/p11 - "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.".)
If CRTP<Derived, Base>::DoSomething() is indeed instantiated, then the situation is covered by §14.6.4.1 [temp.point]/p5 and p8 (emphasis mine):
5 If a virtual function is implicitly instantiated, its point of
instantiation is immediately following the point of instantiation of
its enclosing class template specialization.
8 A specialization for a function template, a member function template,
or of a member function or static data member of a class template may
have multiple points of instantiations within a translation unit, and
in addition to the points of instantiation described above, for any
such specialization that has a point of instantiation within the
translation unit, the end of the translation unit is also considered a
point of instantiation. A specialization for a class template has at
most one point of instantiation within a translation unit. A
specialization for any template may have points of instantiation in
multiple translation units. If two different points of instantiation
give a template specialization different meanings according to the one
definition rule (3.2), the program is ill-formed, no diagnostic
required.
That is, it has two points of instantiation, one right after CRTP< Derived, Base >'s point of instantiation, and one at the end of the translation unit. In this case, at the two points of instantiations name lookup for typename T::Type would produce different results, so the program is ill-formed, no diagnostic required.
The use of new Derived causes the Derived class to be instantiated.
Correction: Derived is not itself a template, so its structure layout and contained member declarations are needed right away. That causes CRTP<Derived,Base> to be instantiated immediately following the Derived definition. I'll have to look up the formal standard later when I have more time; but the the point is still that the instantiation of CRTP only figures out the structure and available members, not the bodies of the member functions; and it knows the structure and members of the Derived class when it does so.
The member functions are not instantiated until they are used (here, the constructor), and it already has the class itself at that time. The other thing to look up is whether the constructor of Derived, since it is not a template, is generated immediately following the class, or only if/when needed. If the former, it can be made lazy by making Derived a template with a dummy argument. But that doesn't affect this specific question: whether right after Derived or right after main, the function instantiation is still not before parsing the declaration of Derived.
That causes CRTP<Derived,Base> to be instantiated. But in both cases it is only the class structure that is needed, not the actual code for any of the members. Erase all the inline function bodies, and you'll see there is no problem at this point.
Now the Derived default constructor is used, so Derived::Derived() is implicitly instantiated. The point of instantiation is immediately following the definition of main.
In instantiating Derived::Derived(), it then needs CRTP<Derived,Base>::CRTP(). It is instantiated at the same point as the template instantiation that needed it. That constructor needs all the virtual functions, so DoSomething() is instantiated, again, at the same point as the instantiation that kicked it off. You can see that all this happens well after the complete definition of the fully rendered Derived class is known, in terms of all the declarations of all the members (not the function bodies).
That's the missing insight: the class definition does not include member function definitions, even if they are given within the lexical enclosing region of the class definition. Remember the distinction between definitions and declarations, separately for classes and functions.
I figured an explicit instantiation request would automatically instantiate all base class members also, but I get a linker error: unresolved external symbol "public: void Base<int>::foo(int)" when building this code using Visual Studio 2008 or 2010.
Note that adding a call to foo() inside bar() forces the compiler to instantiate Base<int>::bar() and the build succeeds, so it appears that the compiler has all the necessary information to instantiate foo().
Obviously, explicitly instantiating Base<int> in source.cpp allows the build to succeed, but it seems silly to need to explicitly instantiate any dependent base classes whenever explicitly instantiating a derived class.
Is this normal? I couldn't find what the standard says regarding this issue.
header.h
template<typename T>
class Base {
public:
void foo();
};
template<typename T>
class Derived : public Base<T> {
public:
void bar();
};
source.cpp
#include "header.h"
template<typename T>
void Base<T>::foo() { }
template<typename T>
void Derived<T>::bar() {
// this->foo(); // adding this forces instantiation of foo()???
}
template class Derived<int>;
main.cpp
#include "header.h"
int main() {
Derived<int> d;
d.foo(); // Linker Error: unresolved external symbol "public: void Base<int>::foo(int)"
}
Edit:
It looks like the Standard says only members of a class get instantiated by an explicit class instantiation, so the linker error is justified in my example.
Note that a class is defined by class-head { member-specification } and "The member-specification in a class definition declares the full set of members of the class; no member can be added elsewhere." So members are only between the curly braces { }, and public base class members don't become members of the derived class, they are merely accessible from the derived class or by objects of the derived class.
My only remaining question is why the Standard specifies that explicit instantiation of a class template only instantiates members and not members of base classes? My guess is that this allows greater control of what gets explicitly instantiated where. Someone that's using explicit template class instantiations would most likely have the base class definitions in a different file than the derived class definitions, and would explicitly instantiate each separately.
The Standard says
The explicit instantiation of a class template specialization implies the instantiation of all of its members not previously explicitly specialized in the translation unit containing the explicit instantiation.
In other words, it does not mandate that base classes are explicitly instantiated in turn. It will cause an implicit instantiation of them which will not instantiate their member definitions up-front. It's some ugly glitch in the Standard as to whether some text when it says "member" means "direct" or "inherited" member, as that often seems to be "obvious" to the one who wrote the Standards wording, but not to the one who reads it. C++0x has added some clarifications (it also has a difference between explicit instantiation declarations and definitions that C++03 doesn't have, but even ignoring that, the C++0x wording contains some more bits of insight):
An explicit instantiation that names a class template specialization is also an explicit instantiation of the
same kind (declaration or definition) of each of its members (not including members inherited from base
classes) that has not been previously explicitly specialized in the translation unit containing the explicit
instantiation, except as described below. [ Note: In addition, it will typically be an explicit instantiation of
certain implementation-dependent data about the class. — end note ]