tags:

views:

615

answers:

7

I know that in the original c++ standard there ware a feature called export.

but i can't find a description or explanation of this feature.

and witch compiler is supporting it?

+5  A: 

See this explanation for its use

Quite a few compilers don't support it either because it's too new or in the case of gcc - because they disaprove.

This post describes standard support for many compilers. http://stackoverflow.com/questions/146381/visual-studio-support-for-new-c-c-standards

Martin Beckett
It's not too new, it's 10 years old like the other features in the C++ 98 standard! :D It's more that implementing it require a redesign of the compiler, and they don't think it's worth it.
KTC
It makes the linker tricky, especially if you want to do lots of clever whole program optimisation in the link stage
Martin Beckett
+1  A: 

The only compilers that support exported templates at the moment (as far as I know) are Comeau, the one that came with Borland C++ Builder X but not the current C++ Builder, and Intel (at least unofficially, if not officially, not sure).

KTC
+1  A: 

To put it simply:

export lets you separate the declaration (ie. header) from the definition (ie. the code) when you write your template classes. If export is not supported by your compiler then you need to put the declaration and definition in one place.

Rodyland
+2  A: 

See here and here for Herb Sutter's treatment of the subject.

Basically: export has been implemented in only one compiler - and in that implementation, export actually increases the coupling between template definition and declaration, whereas the only point in introducing export was to decrease this coupling.

That's why most compilers don't bother. I would have thought they would have just removed export from the language in C++0x, but I don't think they did. Maybe some day there will be a good way to implement export that has the intended use.

Greg Rogers
Herb Sutter is a Microsoft employee. He has tried to remove export from C++0x, and failed. So his opinion might be somewhat biased. Disclosure: I voted down his proposal to ISO.
MSalters
Care to comment on why? Everything I've been able to dig up on this implies that the feature is a dead issue, whether or not it remains in the standard.
T.E.D.
Sutter being a MS employee don't have anything to do with it, he just think export didn't work out, so think it should be removed.
KTC
It will definitely be in C++0x. Sutter proposed to remove it for C++0x, and after discussion, the proposal failed. C++0x is feature complete, what's in the draft now will be what's in the final version less bug fixes.
KTC
@KTC: sure? In the final draft I have, 2.12 [lex.key]/1 it says: "The identifiers shown in Table 3 are reserved for use as keywords (that is, they are unconditionally treated as keywords in phase 7) except in an attribute-token (7.6.1) [Note: The export keyword is unused but is reserved for future use. — end note]" That seems to say that in the current draft the `export` feature is gone. Also note that the only compiler implementor that had support for `export` pushed for the removal of the feature from the new standard.
David Rodríguez - dribeas
@KTC: I have found this other [link](http://herbsutter.com/2010/03/13/trip-report-march-2010-iso-c-standards-meeting/) with comments after the March 2010 meeting when they removed the feature. So you were right (back when you wrote the comment) that the feature was still available even if that no longer holds.
David Rodríguez - dribeas
@David Rodríguez, Well yeah, it was supposed to be "feature complete" when I wrote that comment. They then started taking off features again, including a re-discussion and subsequent removal of export.I wouldn't say EDG pushed for its removal, but rather that they were okay with it. Herb's comment in the linked article regarding EDG is actually very interesting.
KTC
A: 

Export is a feature that introduces a circular dependency between linker and compiler. As others noted, it allows one translation unit to contain the definition of a template used in another. The linker will be the first to detect this, but it needs the compiler for the instantiation of the template. And this involves real hard work, like name lookup.

Comeau introduced it first, about 5 years ago IIRC. It worked quite well on the frist beta release I got. Even testcases like A<2> using B<2> using A<1> using B<1> using A<0>, worked, if templates A and B came from different TU's. Sure, the linker was repeatedly invoking the compiler, but all name lookups worked OK. Instantiation A<1> found names from A.cpp that were invisible in B.cpp.

MSalters
+1  A: 

Although Standard C++ has no such requirement, some compilers require that all function templates need to be made available in every translation unit that it is used in. In effect, for those compilers, the bodies of template functions must be made available in a header file. To repeat: that means those compilers won't allow them to be defined in non-header files such as .cpp files. To clarify, in C++ese this means that this:

// ORIGINAL version of xyz.h
 template <typename T>
 struct xyz
  {
     xyz();
     ~xyz();
  };

would NOT be satisfied with these definitions of the ctor and dtors:

   // ORIGINAL version of xyz.cpp
  #include "xyz.h"

  template <typename T>
  xyz<T>::xyz() {}

 template <typename T>
 xyz<T>::~xyz() {}

because using it:

// main.cpp #include "xyz.h"

 int main()
  {
  xyz<int> xyzint;

  return 0;

}

will produce an error. For instance, with Comeau C++ you'd get:

C:\export>como xyz.cpp main.cpp C++'ing xyz.cpp... Comeau C/C++ 4.3.4.1 (May 29 2004 23:08:11) for MS_WINDOWS_x86 Copyright 1988-2004 Comeau Computing. All rights reserved. MODE:non-strict warnings microsoft C++

C++'ing main.cpp... Comeau C/C++ 4.3.4.1 (May 29 2004 23:08:11) for MS_WINDOWS_x86 Copyright 1988-2004 Comeau Computing. All rights reserved. MODE:non-strict warnings microsoft C++

main.obj : error LNK2001: unresolved external symbol xyz::~xyz() [with T1=int] main.obj : error LNK2019: unresolved external symbol xyz::xyz() [with T1=int] referenced in function _main aout.exe : fatal error LNK1120: 2 unresolved externals

because there is no use of the ctor or dtor within xyz.cpp, therefore, there is no instantiations that needs to occur from there. For better or worse, this is how templates work.

One way around this is to explicitly request the instantiation of xyz, in this example of xyz. In a brute force effort, this could be added to xyz.cpp by adding this line at the end of it:

template xyz;

which requests that (all of) xyz be instantiated. That's kind of in the wrong place though, since it means that everytime a new xyz type is brought about that the implementation file xyz.cpp must be modified. A less intrusive way to avoid that file is to create another:

// xyztir.cpp

include "xyz.cpp" // .cpp file!!!, not .h file!!

template xyz;

This is still somewhat painful because it still requires a manual intervention everytime a new xyz is brought forth. In a non-trivial program this could be an unreasonable maintenance demand.

So instead, another way to approach this is to #include "xyz.cpp" into the end of xyz.h:

// xyz.h

// ... previous content of xyz.h ...

include "xyz.cpp"

You could of course literally bring (cut and paste it) the contents of xyz.cpp to the end of xyz.h, hence getting rid of xyz.cpp; it's a question of file organization and in the end the results of preprocessing will be the same, in that the ctor and dtor bodies will be in the header, and hence brought into any compilation request, since that would be using the respective header. Either way, this has the side-effect that now every template is in your header file. It could slow compilation, and it could result in code bloat. One way to approach the latter is to declare the functions in question, in this case the ctor and dtor, as inline, so this would require you to modify xyz.cpp in the running example.

As an aside, some compilers also require that some functions be defined inline inside a class, and not outside of one, so the setup above would need to be tweaked further in the case of those compilers. Note that this is a compiler issue, not one of Standard C++, so not all compilers require this. For instance, Comeau C++ does not, nor should it. Check out http://www.comeaucomputing.com/4.0/docs/userman/ati.html for details on our current setup. In short, Comeau C++ supports many models, including one which comes close to what the export keyword's intentions are (as an extension) as well as even supporting export itself.

Lastly, note that the C++ export keyword is intended to alleviate the original question. However, currently Comeau C++ is the only compiler which is being publicized to support export. See http://www.comeaucomputing.com/4.0/docs/userman/export.html and http://www.comeaucomputing.com/4.3.0/minor/win95+/43stuff.txt for some details. Hopefully as other compilers reach compliance with Standard C++, this situation will change. In the example above, using export means returning to the original code which produced the linker errors, and making a change: declare the template in xyz.h with the export keyword:

// xyz.h

export // ... ORIGINAL contents of xyz.h ...

The ctor and dtor in xyz.cpp will be exported simply by virtue of #includeing xyz.h, which it already does. So, in this case you don't need xyztir.cpp, nor the instantiation request at the end of xyz.cpp, and you don't need the ctor or dtor manually brought into xyz.h. With the command line shown earlier, it's possible that the compiler will do it all for you automatically.

BE Student