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).
Related
P0040R3 (adopted 2016-06, see also N4603) introduced some extended memory management algorithms like std::uninitialized_move_n into the draft, and finally it became parts of ISO C++17. Some of them had an extra overload with a ExecutionPolicy parameter for potential support of parallelism.
However, as of now (Aug 2018), I don't find any standard library implementation shipped with the implementations of these overloads. And the documentation of implementations I've checked does not clarify it well. Specifically, (currently) they are:
libstdc++ shows it does not support P0040R3 in trunk, but actually at least std::destroy_at and std::uninitialized_move_n without ExecutionPolicy are in GCC 8.2.
libc++ has "Complete" support of P0040R3 since 4.0, but the overloads with ExecutionPolicy are actually missing.
Microsoft VC++ has support of P0040R3 since VS 2017 15.3 with /std:c++17 or /std:c++latest, but the overloads with ExecutionPolicy are actually missing.
The only implementation with ExecutionPolicy overloads I know is in HPX, but this is not a full implementation of the standard library. If I want to use the features portably, I have to adapt to custom implementation likewise, rather than direct use of std names. But I still want to use std implementation in future as preference (unless they have known bugs). (The reason is that implementation-defined execution policies are tightly coupled with concrete implementations, so external implementations as well as their client code would likely have less opportunity to utilize various execution policies in general; although this is not necessarily true for client code which is not guaranteed portable in the sense of conforming to standard.) Thus, I want something available for conditional inclusion in my potable adaptive layer for implementations - to get the specified features with using std::... when they are provided by the standard library, and complement it with my implementations as the fallback of missing parts from the standard library implementation only when necessary.
As I have known, the SD-6 feature testing macros as well as P0941R2 shows __cpp_lib_raw_memory_algorithms is sufficient for the features in P0040R3. On the other hand, __cpp_lib_parallel_algorithm seems not related to <memory> at all. So there is no way to express the state like current libc++ and MSVC implementations - with std names from P0040R3 but lack of ExecutionPolicy overloads. And I'm not sure __has_include<execution> would ever work. The reality may be quirkier, e.g. P0336R1 is even not supported by libc++.
So, how to get it perfectly portable in my code when the features become (hopefully) available in some newer version of the standard library implementations, except inspecting the source of each version of them, or totally reinventing my wheels of the whole P0040R3?
Edited:
I know the intended use of feature testing macros and I think libstdc++ has done the right thing. However, there is room to improve. More specifically, my code of the portable layer would play the role of the implementation (like HPX), but more "lightweight" in the sense of not reinventing wheels when they are already provided by the standard library implementation:
namespace my
{
#if ???
//#if __cpp_lib_raw_memory_algorithms
using std::uninitialized_move_n;
// XXX: Is this sufficient???
#else
// ... wheels here ... not expected to be more efficient to std counterparts in general
#endif
}
so my client code can be:
my::uninitialized_move_n(???::par, iter, size, d_iter);
rather than (copied from Barry's answer):
#if __cpp_lib_raw_memory_algorithms
std::uninitialized_move_n(std::execution::par, iter, size, d_iter);
#else
// ???
#endif
Both pieces of the code can work, but obviously checking __cpp_lib_raw_memory_algorithms directly everywhere in client code is more costly.
Ideally I should have some complete up-to-date standard library implementation, but that is not always the case I can guarantee (particularly working with environments where the standard library is installed as parts of system libraries). I need the adaption to ease the clients' work anyway.
The fallback is obvious: avoiding the using std::uninitialized_move_n; path totally. I'm afraid this would be a pessimistic implementation so I want to avoid this approach when possible.
Second update:
Because "perfectly portable" sounds unclear, I have illustrated some code in the edit above. Although the question is not changed and still covered by the title, I will make it more concrete here.
The "perfectly portable" way I want in the question is restricted as, given the code like the edit above, filling up any parts marked in ???, without relying on any particular versions of language implementations (e.g., nothing like macro names depended on implementations should be used for the purpose).
See here and here for the code examples fail to meet the criteria. (Well, these versions are figured out via inspection of commit logs... certainly imperfect, and, still buggy in some cases.) Note this is not related to the overloads with ExecutionPolicy yet, because they are missing in the mentioned standard library implementations, and my next action is depending on the solution of this question. (But the future of the names in std should be clear.)
A perfect (enough) solution can be, for example, adding a new feature testing macro to make the overloads independent from __cpp_lib_raw_memory_algorithms so in future I can just add my implementation of the overloads with ExecutionPolicy when they are not detected by the stand-alone new feature testing macro, without messing up the condition of #if again. But certainly I can't guarantee this way would be feasible; it ultimately depends on the decision of the committee and vendors.
I'm not sure whether there can be other directions.
The initial version of P0941 contained a table which made it clear that P0040R3 has the corresponding feature-test macro __cpp_lib_raw_memory_algorithms. This implies that the correct, portable way to write code to conditionally use this feature is:
#if __cpp_lib_raw_memory_algorithms
std::uninitialized_move_n(std::execution::par, iter, size, d_iter);
#else
// ???
#endif
The imposed requirement is that if that macro is defined, then that function exists and does what the standard prescribes. But that macro not being defined does not really say anything. As you point out, there are parts of P0040R3 that are implemented in libstdc++ - parts, but not all, which is why the feature-test macro is not defined.
There is currently a concerted effort to implement the parallel algorithms in libstdc++.
As to what to do in the #else branch there, well... you're kind of on your own.
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.
I am developing a Library for Matrix Calculations in C++. For this I wanted to use Templates. After doing a bit of Template Meta Programing, I realized that I would end up in exposing my implementations in the Templatise Matrix Class.Is there any way to obfuscate the template class implementation in the header file when you expose that particular template class ? If yes, then how is it done ?
I will answer from the customer perspective.
When I need to use a library, and integrate it in my code, I expect to see the source code.
It is not because I wish to rip it out from the author... It is not because I am a lawless and irrespective hacker...
It is, simply, because:
code is documentation, and seeing the implementation of a method will help me compensate for the lack of it, or perhaps better understand what it meant (*)
for debugging, the ability to step down into library's code is invaluable
for developing, it is just so much easier if I can compile the code myself, in various flavors (with and without instrumentation, aka gcov, with and without debug symbols, etc...)
I don't ask for the code to be free, I am perfectly fine with the code being licensed, and I'll scrupulously follow the license terms, I just ask for the code to be available.
Frankly, if I have the choice between two libraries, and one does not expose its code, I'll lean toward the other, unless the performance/correctness difference is really important.
(*) In C++, Boost has libraries that I consider fundamentally broken in this regard. The code is riddled with compilers work-around, which makes it very difficult to read. Nevertheless, I use them because they're just awesome.
As templating means that the implementation of the class/function is created compile-time (needs to make a new implementation for each new type) I cannot see how you could hide the code. The only way would be to hide your templates in a precompiled library and only expose interfaces to predefined types. That would lose the template functionality though...
With current standard (and even upcoming C++11), one has to expose all the template definitions where those templates are used. There is no standard way to hide it.
Second part, if you choose to obfuscate it, then equally its usage will become complex. The best way in my opinion is to license/copyright them!
I think all template-based C++ libs are deployed as header files (perhaps also using libraries but the publicly usable templates have to be headers). That's true for STL, boost, etc. It's simply the way templates work -- the compiler has to see the original template.
In addition to all the other reasons cited, there's another problem: C++ names are "decorated" - for example in order to support method overloads, the types of the parameters for the method are encoded in the name of the method.
There is no standard for this encoding, it varies from compiler to compiler and even from one version of a compiler to another version of the same compiler.
As a result, if you have a library containing C++ functions, you can't ensure that the names of the functions can be read by your clients (unless you can guarantee that your clients are using the same version of the compiler that you are).
For standard libraries, this isn't a problem, since the libraries are shipped with the compiler, but for other libraries, you need to be very careful.
No, not really, since a template is not compiled code. It's literally a "template". When a template is instantiated in a .cpp file, the template itself needs to be available to the compiler in order to generate the code for the class method. Therefore you can't "hide" the template code ... it has to be available to the compiler, or else you are going to be unable to compile any modules that attempt to instantiate the template.
One good way to think of templates is like a blank form you might use, say for income-taxes or something of that nature. In order to actually make a valid income-tax form, meaning one filled out with your name, SSN, etc., you need a copy of the "blank" original. So you can't "hide" the form from a person and expect them to fill it out correctly. The same is true for the compiler. When you instantiate a template function or class, a copy of the template needs to be made available for the compiler to fill in the template parameters and actually generate the "real" code behind-the-scenes for you that is then compiled in the code module.
You can put your code in a precompiled header, but I must agree that best way to protect your code is to put license/copyright.
I am updating a code base that is 10 years old and used Metrowerks Code Warrior on Mac and Windows.
I am updating to OS X, XCode 3.2, Universal Binary.
I seem to be getting a lot of template related errors and not being a genius on templates (and forgetting to eat a healthy dose of frosted templates for breakfast), I find myself wondering about template portability issues.
IIRC, templates are/or can be compiler specific?
Does anyone have advice or a tutorial on templates that they recommend?
Yes and no -- most reasonable template code written for one current compiler will work fine on other current compilers. Compilers have progressed over time, so a lot of new code won't work on old compilers, and vice versa. The biggest culprit with old code on new compilers is needing "typename" in quite a few places that old compilers would accept the code without it.
The most common problem is with code something like this:
template <class T>
class XYZ {
T::y a;
};
Most older compilers would (incorrectly) interpret "T::y" as a type -- but in a template, it's actually impossible to be sure of that, because T might be any type. To make the code work with a modern (more accurate) compiler, you need to change that to: typename T::y a;, to let the compiler know that T::y is the name of a type.
Templates themselves have well-defined behavior, as defined in ยง14 in the standard.
What is implementation-dependent is the limits of template use. For example, from Annex B (which lists recommended limit minimums):
Template arguments in a template declaration [1024].
Recursively nested template instantiations [17].
If you're depending on behavior more than these, it may be implementation dependent. It should be noted a compiler does not have to provide these minimal limits to remain standards compliant.
If you post some actual code/errors, we can tell you why you're getting an error. Likely, you're old code used some compiler-specific extensions or otherwise was allowed to use explicitly forbidden behavior.
The ability of compilers has improved a lot in ten years.
I would question the standards compliance of the compiler and the STL from 10 years ago. I belive tha standard had only just been introduced ten years ago and it takes compilers a while to catch up with the standard.
In modern compilers I think you will find that template code is relatively portable across compilers and the standards comitee is very carefull about changes to the standard to make sure it does not break compatabilty (very often).
There wasn't a single compiler in 2000 which implemented all aspects of standard templates. I'd dare to say no one even realised what was possible with templates till Alexandrescu released his Modern C++ design in 2001.
That said, Metrowerks was one of the better ones. If it compiles on version 7 or later, it should be very feasible to get it working on a modern, more standard compliant, compiler rather fast.
If I remember correctly the biggest problem with Metrowerks compilers in the early days was that wherever typename appeared, what followed was simply interpreted as a type, no matter what followed it.
This meant you could do, and I've seen, completely non standard stuff with that, like forward declaring typedefs.
Another part of templates that took them pretty long to get right was everything w.r.t. template template parameters and default template arguments.
Post some specific errors if you can't get it to work, they'll probably all fall in one or two 'classes' of problems, and someone will quickly be able to help you.
As I already said, Metrowerks had a pretty good C++ compiler, especially their STL implementation, largely thanks to Howard Hinnant I think.
C++ seems to be rather grouchy when declaring templates across multiple files. More specifically, when working with templated classes, the linker expect all method definitions for the class in a single compiler object file. When you take into account headers, other declarations, inheritance, etc., things get really messy.
Are there any general advice or workarounds for organizing or redistributing templated member definitions across multiple files?
Are there any general advice or workarounds for organizing or redistributing templated member definitions across multiple files?
Yes; don't.
The C++ spec permits a compiler to be able to "see" the entire template (declaration and definition) at the point of instantiation, and (due to the complexities of any implementation) most compilers retain this requirement. The upshot is that #inclusion of any template header must also #include any and all source required to instantiate the template.
The easiest way to deal with this is to dump everything into the header, inline where posible, out-of-line where necessary.
If you really regard this as an unacceptable affront, a common option is to split the template into the usual header/implementation pair, and then #include the implementation file at the end of the header.
C++'s "export" feature may or may not provide another workaround. The feature is poorly supported and poorly defined; although it in principle should permit some kind of separate compilation of templates, it doesn't necessarily obviate the demand that the compiler be able to see the entire template body.
Across how many files? If you just want to separate class definitions from implementation then try this article in the C++ faqs. That's about the only way I know of that works at the moment, but some IDEs (Eclipse CDT for example) won't link this method properly and you may get a lot of errors. However, writing your own makefiles or using Visual C++ has always worked for me :-)
When/if your compiler supports C++0x, the extern keyword can be used to separate template declarations from definitions.
See here for a brief explanation.
Also, section 6.3, "The Separation Model," of C++ Templates: The Complete Guide by David Vandevoorde and Nicolai M. Josuttis describes other options.