Once I saw a statement that "separately compiled C++ templates" is a standard feature that none of available C++ compilers support.
What are those "separately compiled templates" and why are they ignored?
C++98 introduced the export keyword which allowed you to have the definition of a function template in another translation unit, with only its declaration needed to compile code that uses it. (See here if you are hazy on what's a definition vs. a declaration. Basically, you could have the function templates implementation in another translation unit.) That's just as it is with other functions.
However, only compilers using EDG's compiler front end ever supported it, and not all of them even did officially. In fact, the only compiler I know that officially supported it was Comeau C++. That's why the keyword, unfortunately, got removed from C++11.
I think it's safe to say that it is expected that a proper module system would cure C++ from many of its shortcomings that surround the whole compilation model, but, again unfortunately, a module system was not considered something that could be tackled in a reasonable amount of time for C++11. We will have to hope for the next version of the standard.
Separately compiled templates is where you can bring in template definitions from another translation unit instead of having to define them in every TU (normally in the header).
Basically, they're ignored because they're virtually impossible to implement in terms of complexity and bring a number of unfortunate side effects.
Related
Inspired by this 2009 question
Background: I'm currently working on a small c++ project and decided to try my hand at creating my own templated classes. I immediately ran into a dozen linker errors.
As it stands, my understanding is that template specializations aren't generated until they absolutely need to be, and this implies that the implementation of a templated class must be either inlined, or accompanied by an explicit instantiation at the bottom. (Why one implies the other I'm not so sure)
Question: Why is that so? Is there something special about the order of compilation that makes it impossible for a compiler to instantiate the template on-demand if it is implemented in a separate .cpp file? In my mind the header and the implementation were simply appended together.
Additionally, the question I linked above was initially posted more than ten years ago, and some comments note that the c++-faq quote mentioned is out of date, so I was wondering if newer standards support solutions that enable both separate header/implementation files and implicit instantiation.
Why is it so?
As templates compiles through two phases in first phase compiler checks mostly for syntactical errors. If there is no error found in your template is legal to be used, but at this stage compiler do not generate any code for it. And in the second phase compiler will generate the code for all the class members function, of templated functions you used.
Because templates are evaluated at compile time. So what happens when compiler compiles it? For example if you defined a template in templated.hpp file and its implementation in implementation.cpp file. Compiler compiles each file separately into an object and then linker link them together. As templates are evaluated at compile time so compiler need its implementation at compile time, which is not available if you are having it in different implementation file. So linkers complains to you that I could not find implementation for type T for your this template. This all happens at compile time.
So far until C++20 or even C++23 templates are still needed to be evaluated at compile time albeit C++ has added new concept modules, I am not sure it can be used this way, but you can read about it here.
I am aware that the keyword inline has useful properties e.g. for keeping template specializations inside a header file.
On the other hand I have often read that inline is almost useless as hint for the compiler to actually inline functions.
Further the keyword cannot be used inside a cpp file since the compiler wants to inspect functions marked with the inline keyword whenever they are called.
Hence I am a little confused about the "automatic" inlining capabilities of modern compilers (namely gcc 4.43). When I define a function inside a cpp, can the compiler inline it anyway if it deems that inlining makes sense for the function or do I rob him of some optimization capabilities ? (Which would be fine for the majority of functions, but important to know for small ones called very often)
Within the compilation unit the compiler will have no problem inline functions (even if they are not marked as inline). Across compilation units it is harder but modern compilers can do it.
Use of the inline tag has little affect on 'modern' compilers and whether it actually inlines functions (it has better heuristics than the human mind) (unless you specify flags to force it one way or the other (which is usually a bad idea as humans are bad at making this decision)).
Microsoft Visual C++ was able to do so at least since Visual Studio 2005. They call it "Whole Program Optimization" or "Link-Time Code Generation". In this implementation, the compiler will not actually produce machine code, but write the preprocessed C++ code into the object files. The linker will then merge all of the code into one huge code unit and perform the actual compilation..
GCC is able to do this since at least version 4.5, with major improvements coming in GCC 4.7. To my knowledge the feature is still considered somewhat experimental (at least in so far as many Linux distributions not using it). GCC's implementation works very similarly by first writing the preprocessed source (in its GIMPLE intermediate language) into the object files, then compiling all of the object files into a single object file which is then passed to the linker (this allows GCC to continue to work with existing linkers).
Many big C++ projects also do what is now being called "unity builds". Instead of passing hundreds of individual C++ source files into the compiler, one source file is created that includes all the other source files in the project. The original intent behind this is to decrease compilation times (since headers etc. do not have to be parsed over and over), but as a side-effect, it will have the same outcome as the LTO/LTCG techniques mentioned above: giving the compiler perfect visibility into all functions in all compilation units.
I jump between being impressed by my C++ compiler's (MSVC 2010) ingenuity and its stupidity. Some code that did pixel format conversion via templates, which would have resolved into 5-10 assembly instructions when properly inlined, got bloated into kilobytes(!) of nested function calls. At other times, it inlines so aggressively that whole classes disappear even though they contained non-trivial functionality.
This depends on your compilation flags. With -combine and -fwhole-program, gcc will do function inlining across cpp boundaries. I'm not sure how much the linker will do if you compile into multiple object files.
The standard dictates nothing about how a function can be inlined. And compilers can inline functions if they have access to their implementation. If you only have a header with binaries, it would be impossible. If it's in the same module, the compiler can inline the function even if it is in the cpp file.
I understand that you can't declare a virtual method as templated, because the compiler would not know how much entries to reserve in the virtual table. This is, however, a technical limitation, rather than a language one. The compiler could know how many instances of the template are actually needed, and "go back" to allocate a proper vtable size.
Is there a planned technical solution in the upcoming standard?
The compiler can never know all of the possible instantiations of a template. Under the current compilation model, each translation unit is compiled separately and later linked. When compiling a template type in one translation unit, you do not know the instantiations of that type in another.
Imagine you're writing a library and you want a template function in it. You compile the library and then distribute it to your clients. Now the clients can instantiate your template function with whatever template arguments they like, but your library has already been compiled! It can't "go back" and change this.
You're assuming that when you compile the template function, you also have available every instantiation of that function. That's often not the case and, under the current compilation and linking model, cannot be known to be the case.
It's certainly possible to do this, given no requirements of working with existing linkers. That is, the linker could sift through all the instantiations of that template function and build the appropriate data structures. But one of the strengths of C++ is that it doesn't require specialized linkers; that makes it portable to systems where the linker is written in stone and cannot be changed. And, yes, that happens; the linker is where all the object code meets, and it has to be compatible with all the programming languages that the system supports, and that, in turn, means that it sometimes has grown old and crufty, and any change brings a substantial risk of breakage. So, while it's theoretically possible to do this, it ain't gonna happen.
There is nothing currently planned based on the C++ Standards Committee papers and core language issues. The C++ Standard specifies requirements for implementations of C++, but not define the technical implementation itself. Hence, template virtual functions are explicitly not a technical limitation, but rather a limitation of the language defined by the standard. Nevertheless, the limitation of the language may be the result of the risk involved in changing existing implementations rather than being imposed as a result of an implementation's technical limitations.
As i Understand "export" keyword can be used so that one can expose template classes or function signatures through an header file and abstract the actual implementation in a library file.
Can anyone please provide a practical sample program which shows how to do this?
Are there any disadvantages or important points to note while using this?
EDIT: A follow up question based on the answers. As mentioned in the answers 'export' is deprecated in C++0x and rarely supported by compilers even for C++03x. Given this situation, in what way can one hide actual implementations in lib files and just expose declarations through header files, So that end user can know what are the signatures of the exposed API but not have access to the source code implementing the same?
Attention: This answer is about the historical use of export pre-C++20; C++20 repurposes the keyword for use in modules.
First of all: most compilers (including gcc, Clang and Visual Studio) do not support the export keyword.
It has been implemented in a single front-end: the EDG front-end, and thus only the compilers that use it (Comeau and icc) support this feature. The feedback from the implementers at EDG was extremely simple: it took us time, was extremely complicated, we recommend not to implement it (1), as a consequence it has been dropped in C++0x.
Now, the standard allows (and this is implemented by at least gcc):
to declare a specialized version of a template function in a header
to define this specialization in a single source file
and to have it behave as you'd expect from a regular function.
Note: as Johannes points out in a comment, if a full specialization of a function is defined in a header, it must be marked as inline otherwise the linker will complains.
EDIT:
(1) Finally found my reference Why can't we afford export (PDF) by Tom Plum, reviewed by Steve Adamczyk, John Spicer, and Daveed Vandevoorde of Edison Design Group who originally implemented it in the EDG front end.
Export has been removed from the C++ standard. Do not use it.
It's difficult to provide a sample program because almost no compilers support export. g++ will report a warning saying that it's not supported, and IIRC it doesn't even compile in Visual Studio. Moreover, export is deprecated in C++0x, meaning that it's unlikely that future compilers will support it at all.
For a discussion of how to use export in the few compiles that do support it (namely Comeau C++), check out this link which also goes into why export is hard to implement.
And apologies if this comes across as a major anti-export rant. I promise that I don't hate export! It's just not widely supported and you can't really rely on it as a programmer.
The reasons many compiler vendors did not support it is that even when it works it does not do so the way programmers would expect.
The best article I found on the issues is here:
http://msmvps.com/blogs/vandooren/archive/2008/09/24/c-keyword-of-the-day-export.aspx
You are better off instantiating your templates.
I read an article with the title something like Export is not supported and it wouldn't do what you want anyway.
The only way to do what you want is to fully specialize as has been said. But more than that, if you can't see the source code of a library then you can't compile it. This means you cannot accept dynamic memory from it since there is no guarantee you will use the matching delete to their new. For example, if my code is debug and the library is release the deleter will not match the new. You could use shared_ptr and provide a deleter, but that's TR1 and does not have export.
C++11 now has 'extern templates' which are already well supported by modern compilers.
The export keyword is supported in C++20 and is used with the modules language feature (https://en.cppreference.com/w/cpp/language/modules).
I've few questions about C++ compilers
Are C++ compilers required to be one-pass compiler? Does the Standard talk about it anywhere?
In particular, is GCC one-pass compiler? If it is, then why does it generate the following error twice in this example (though the template argument is different in each error message)?
error: declaration of ‘adder<T> item’ shadows a parameter
error: declaration of ‘adder<char [21]> item’ shadows a parameter
A more general question
What are the advantages and disadvantages of one-pass compiler and multi-pass compiler?
Useful links:
A List of C/C++ compilers (wikipedia)
An incomplete list of C++ compilers (Bjarne Stroustrup's site)
The standard sets no requirements what so ever with regards to
how a compiler is implemented. But what do you mean by
"one-pass"? Most compilers today do only read the input file
once. They create an in memory representation (often in the
form of some sort of parse tree), and may make multiple passes
over that. And almost certainly make multiple passes over parts
of it. The compiler must make a "pass" over the internal
representation of a template each time it is instantiated, for
example; there's no way of avoiding that. G++ also makes
a "pass" over the template when it is defined, before any
instantiation, and reports some errors then. (The standard
committee expressedly designed templates to allow a maximum of
error detection at the point of definition. This is the
motivation behind the requirement for typename in certain
places, for example.) Even without templates, a compiler will
generally have to make two passes over a class definition if
there are functions defined in it.
With regards to the more general question, again, I think you'd
have to define exactly what you mean by "one-pass". I don't
know of any compiler today which reads the source file several
times, but almost all will visit some or all of the nodes in the
parse tree more than once. Is this one-pass or multi-pass? The
distinction was more significant in the past, when memory wasn't
sufficient to maintain much of the source code in an internal
representation. Languages like Pascal and, to a lesser degree
C, were sometimes designed to be easy to implement with a single
pass compiler, since a single pass compiler would be
significantly faster. Today, this issue is largely irrelevant,
and modern languages, including C++, tend to ignore it; where
C++ seems to conform to the needs of a one-pass compiler, it's
largely for reasons of C compatibility, and where
C compatibility is not an issue (e.g. in a class definition), it
often makes order of declaration irrelevant.
From what I know, 30 years ago it was important for a compiler to be one-pass, because reads and writes to disk (or magnetic tape) were very slow and there was not enough memory to hold whole code (thanks James Kanze). Also, a single-pass is a requirement for scripting/interactive languages.
Nowdays compilers are usually not one-pass, there are several intermediate representations (e.g Abstract Syntax Tree or Static Single Assignment Form) that the code is transformed into and then analised/optimised.
Some elements in C++ cannot be solved without some intermediate steps, e.g. in a class you can reference members which are defined only later in the class body. Also, all templates need to be somehow remembered for further access during instantiation.
What does not happen usually, is that the source code is not parsed several times --- there is no need for that. So you should not experience same syntactic error being reported several times.
No, I would be surprised if you found a heavily used C++ single pass compiler.
No, it does multiple passes and even different optimizations based on the flags you pass it.
Advantages (single-pass): fast! Since all the source only needs to be examined once the compilation phase (and thus beginning of execution) can happen very quickly. It is also a model that is attractive because it makes the compiler easy to understand and often times "easier" to implement. (I worked on a single pass Pascal compiler once, but don't encounter them often, whereas single pass interpreters are common)
Disadvantages (sinlge-pass): Optimization, semantic/syntactic analysis. Sometimes a single code look lets things through that are easily caught by simple mechanisms in multiple passes. (kind of why we have things like JSLint)
Advantages (multi-pass): optimizations, semantic/syntactic analysis. Even pseudo interpreted languages like "JRuby" go through a pipeline compilation process to get to java/jvm bytecode before execution, you could consider this multi-pass and the multiple looks at the varying representations (and consequently the resulting optimizations) of code can make it very fast.
Disadvantages (multi-pass): complexity, sometimes time (depending on if AOT/JIT is being used as your compilation method)
Also, single-pass is pretty common in academia to help learn the aspects of compiler design.
Walter Bright, the developer of the first C++ compiler, has stated that he believes it is not possible to compile C++ without at least 3 passes. And, yes, that means 3 full text-transforming passes over the source, not just traversals through an internal tree representation. See his Dr. Dobb's magazine article, "Why is C++ compilation so slow?" So any hope of finding a true one-pass compiler seems doomed. (I think this was part of the motivation Bright had to develop D, his C++ alternative.)
The compiler only needs to look at the sources once top down, but that does not mean that it does not have to process the parsed contents more than once. In particular with templates, it has to instantiate the templated code with the type, and that cannot happen until the template is used (or explicitly instantiated by the user), which is the reason for your duplicate errors:
When the template is defined, the compiler detects an error and at that point the type has not been substituted. When the actual instantiation occurs it substitutes the template arguments and processes the result, which is what triggers the second error. Note that if the template was specialized after the first definition, and before the instantiation, for that particular type, the second error need not occur.