Does a C++ compiler generates code if a function template or a class template is specialized but not actually used? I know it will not, if not specialized (function or class template) and not used.
--Thanks
Technically the compiler may choose to eliminate your specialization since it's elimination would not affect the observable behavior of your program. See the as-if rule. Compilers generally provide facilities for exporting symbols such that they are preserved even if unused.
Related
Validity of a non-template code is more or less clear to everyone - a compiler checks the syntax, types, and rules. The compiler has everything it needs to perform these checks.
But when the compiler has to compile a templated code (for example STL, or Boost) it does't have enough information.
While the templated code isn't instantiated the compiler doesn't know what operations mean, whether or not they are defined for the types that will be used to instantiate this templated code, etc. Templated code can't be compiled untill instantiated.
Is there such a thing as a validity of a templated code? Would it require us to compile every instantiation of a templated code to verify its validity?
The standard talks about such validity:
The validity of a template may be checked prior to any instantiation. [ Note: Knowing which names are type names allows the syntax of every template to be checked in this way. — end note ]
As the note says, the reliable check is merely syntactic (or grammar-based). Even rules like looking up non-dependent names are covered by the rule that any template that cannot be instantiated is ill-formed, no diagnostic required. The implementation may then do anything at all, including compiling a program that does… something. (This is really too much implementation freedom; some of these rules could just be “may be ill-formed (with a diagnostic) at the implementation’s discretion”.)
I read from multiple sources that:
If no user-declared constructors of any kind are provided for a class type (struct, class, or union), the compiler will always declare a default constructor as an inline public member of its class.
Why was this decision made (to explicitly declare ctors/dtors as inline)? Compilers are free to inline / non-inline this anyways? Especially since inlining ctors may have a huge penalty on the clients of a class (Effective C++, Item #30)?
They're not inline in the sense "they will always be inlined by the compiler." They are inline in the sense "considered defined in every translation unit which sees the class definition, without violating the One Definition Rule (ODR)." Note that the latter is the only meaning of the phrase "inline function" which standard C++ uses.
Explicitly marking a function with the inline keyword is also a non-binding hint to the compiler to actually inline the function, but I doubt modern compilers & optimisers pay much attention to this hint. However, note that this (hint to inline) applies only to using the keyword inline, and not to functions implicitly inline (such as the defaulted constructor and destructor mentioned in the question).
inline has two meanings in the C++ standard.
The first is what you think of when you hear inline; taking the code in the function and injecting it into the place where it is called.
The C++ standard advises implementations to do this when they see an inline method or function, but does not require it. As such action has zero observable behavior changes in the abstract machine that the C++ standard describes, I consider it non-normative advice.
The second has to do with linking. An inline function (or in C++17 a variable) can exist in multiple translation units. Normally this causes an error at link-time; but when the variable or function is inline, instead all but one of the instances of the variable or function are silently discarded. If they differ in any important way, this makes your program ill-formed no diagnostic required.
This second meaning is why implicit ctors and dtors are implicitly inline; it means that no single translation unit has to be chosen for them to "live in". Instead, they are generated everywhere they are needed. They may be preferentially actually inlined into calling code, but most importantly if any vestigial copies of it still exist (because it was not inlined, say), no error occurs at link time, and instead all but one of them are discarded.
See inline in the C++ standard. The wording in the standard is a bit harder to understand, different and more precise than I use above.
When you use a template with numerous methods (like vector) and compile your code, will the compiler discard the code from the unused methods?
A template is not instantiated unless it is used, so there is actually no code to discard.
The standard says (14.7.1/10)
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 instantiation. 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 use of a template specialization in a default argument shall not cause the template to be implicitly instantiated except that a class template may be instantiated where its complete type is needed to determine the correctness of the default argument. The use of a default argument in a function call causes specializations in the default argument to be implicitly instantiated.
So if you can avoid making the template's member functions virtual, the compiler will not generate any code for them (and that might work for virtual functions as well, if the compiler is smart enough).
It depends on your optimization level. At higher optimization settings, yes, dead code elimination will most likely occur.
the compiler, optimizers, and the linker can omit and/or reduce that information. each mature tool likely has options specific to dead code elimination.
with templates, the code may not really be created in the first place (unless instantiated).
certainly not all of it will be removed in every scenario, however (rtti is a silent killer). a bit of caution and testing using your build settings can go a long way to help you reduce the binary sizes and dead code.
Smart compilers will exclude it most likely. Long time ago when I played with Borland C++ Builder, I think, it did not throw out unused template class methods. Can not confirm though
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why should the implementation and the declaration of a template class be in the same header file?
e.g when defining a template class why do the implementations of the class methods need to be in the header? Why can't they be in a implementation file (cpp/cxx)?
A template class is not a class, it's a template that can be used to create a class. When you instantiate such a class, e.g. MyTemplate<int>, the compiler creates the class on the spot. In order to create it, it has to see all the templated member functions (so that it can use the templates to create actual member functions such as MyTemplate<int>::foo() ), and therefore these templated member functions must be in the header.
If the members are not in the header, the compiler will simply assume that they exist somewhere else and just create actual function declarations from the templated function declarations, and this gives you linker errors.
The "export" keyword is supposed to fix this, but few compilers support it (I only know of Comeau).
You can also explicitly instantiate MyTemplate<int> - then the compiler will create actual member functions for MyTemplate<int> when it compiles the cpp files containing the MyTemplate member function definition templates.
They need to be visible for the compiler when they are instantiated. That basically means that if you are publishing the template in a header, the definitions have to be visible by all translation units that include that header if you depend on implicit instantiation.
They need not be defined in the header if you are going to explicitly instantiate the templates, but this is in most cases not a good idea.
As to the reason, it basically boils down to the fact that templates are not compiled when the compiler parses the definition, but rather when they are instantiated, and then they are compiled for the particular instantiation type.
If your compiler supports export, then it doesn't. Only EDG-based compilers support export, and it's going to be removed from C++0x because of that.
Non-exported templates require that the compiler can see the full template definition, in order to instantiate it for the particular types you supply as arguments. For example:
template<typename T>
struct X {
T t;
X(int i): t(i) {}
};
Now, when you write X<float>(5) in some translation unit, the compiler as part of compiling that translation unit must check that the constructor of X is type-correct, generate the code for it, and so on. Hence it must see the definition of X, so that it can permit X<float>(5) but forbid X<char*>(5).
The only sensible way to ensure that the compiler sees the same template definition in all translation units that use it, is to put the definition in a header file. As far as the standard is concerned, though, you're welcome to copy-and-paste it manually, or to define a template in a cpp file that is used only in that one translation unit.
export in effect tells the compiler that it must output a parsed form of the template definition into a special kind of object file. Then the linker performs template instantiation. With normal toolchains, the compiler is smart enough to perform template instantiation and the linker isn't. Bear in mind that template instantiation has to do pretty much everything that the compiler does beyond basic parsing.
They can be in a CPP file.
The problem arises from the fact that the compiler builds the code for a specific instantiation of a template class (eg std::vector< int >) on a per translation unit basis. The problem with defining the functions in a CPP file is that you will need to define every possible form in that CPP file (this is called template specialization).
So for that int vector exampled above you could define a function in a CPP file for the int case using specialization.
e.g
template<> void std::vector< int >::push_back( int& intVal )
Of course doing this can produce the advantage of optimisation for specific cases but it does give you an idea of just how much code bloat can be introduced by STL! At least all the functions aren't defined as inline as a certain compiler used to do ;)
That aspect of template is called the compilation model, not to be confused with the instantiation mechanism which was the subject of How does C++ link template instances.
The instantiation mechanism is the answer to the question "When is the instantiation generated?", the instantiation model is the answer to "Where the source are found?"
There are two standards compilation model:
inclusion, the one that you know, where the definition must be available,
separated, which allows to put the definition somewhere else with the help of the keyword export. That one has been removed from the standard and won't be available in C++0X. One of the raison for removal was that it wasn't widely implemented (only one implementation).
See C++ Templates, The Complete Guide by David Vandevoorde and Nicolai Josuttis or http://www.bourguet.org/v2/cpplang/export.pdf for more information, the separated compilation model being the subject of that later paper.
According to Sergey Ryazanov, his Impossibly Fast C++ Delegates are not comparable:
My delegates cannot be compared. Comparison operators are not defined because a delegate doesn't contain a pointer to method. Pointer to a stub function can be different in various compilation units.
To which one the readers have replied:
"Pointer to a stub function can be different in various compilation units."
AFAIK, this is not true. Compilers are required to re-use template functions generated in different compilation units (this I am sure of - but I think Borland once violated this rule). I think it is because classes (ones not in 'nameless' namespaces) use external linkage and the way you use the stub functions will always prevent them from being inlined (although this shouldn't be an issue either as taking the address of the function will force a non-inline version to be generated and 'external linkage' performed by the linker will eliminate all but one similarly named function (they are assumed and required to be identical by the standard))...
If you define a template function one translation unit (cpp file) and then define the same function differently in another translation unit, only one of the two versions will make it into the final executable. (This actually violates the "One Definition Rule", but works on GCC, at least... not sure about MSVC.) The point is: the address [of the stub] will be the same in different units.
I would urge you to update the article (including comparison capability) if you find this to be true for MSVC - if MSVC is standards conferment, in this regard.
Now the article is four years old and the author hasn't replied to any of the comments during the past three years or so, so I'm wondering if there's any merit to the above comment and whether this specific implementation can indeed be changed to support comparisons.
Does the C++ standard specifically prohibit such usage and if so, are any of the recent compilers actually standard-compliant in that regard?
The code is both standard compliant, and fine. I don't see any place where he violates ODR, and it is true that all instantiations of a function template with the same template parameters should have "the same address" (in a sense that pointers to functions should all be equal) - how this is achieved is not important. ISO C++03 14.5.5.1[temp.over.link] describes the rules in more detail.
So, a comparison could well be defined there in a conformant and portable way.
The so-called stub functions in Impossibly Fast C++ Delegates are static template member functions, which are basically template functions. The same applies for the improved variant Impossibly Fast C++ Delegates, Fixed.
So the question boils down to this:
Do instantiations of a template function (using the same template parameters and definition) in different translation units share the same function pointer address?
According to the C++ standard (ISO C++17, § 17.5.6.1), the answer is yes.
As #Pavel said in his answer, the same applied for the ISO C++03 standard (ISO C++03, § 14.5.5.1).
In other words this approach is standard compliant and delegates are safely comparable - their data compare equal if and only if they are bound to the same function and (in case of member functions) the same object.