Prev: Is it valid to assign a reference from a ternary expression (i.e. operator ?:)
Next: Is it valid to assign a reference from a ternary expression (i.e. operator ?:)
From: Daniel Krügler on 3 Jun 2010 23:34 On 4 Jun., 07:41, Jun <junh...(a)gmail.com> wrote: > Just a stupid problem, since i need to separate codes in header and > source files (for cross reference), > I found it's really difficult to work with templates in separated > source file. > > For example: > > // MyClass.h > > template <class T> > struct MyClass{ > > Template <typename InputIterator> > T getMyBaby(InputIterator first, InputIterator last){} Two observations: Fix the typo ("Template") and be aware that above is already a member *definition*, because of the pair of braces. If you want to define the member outside of the class, you need to change this first to a non-defining declaration like so: template <typename InputIterator> T getMyBaby(InputIterator first, InputIterator last); > }; > > How can I implement getMyBaby in separated cpp file? > > since, > > template<typename InputIterator> T template <class T> > MyClass<T>::getMyBaby( .... ) > > just doesn't work ... "Doesn't work" has very different flavors, so I strongly recommend to describe the precise problem you have (aka: compiler diagnostics). Also note, that there are more than one problem with your attempt: 1) Your out-of-class definition is defective, because it does not follow the required syntax. The correct syntax would be: template <class T> template<typename InputIterator> T MyClass<T>::getMyBaby(InputIterator first, InputIterator last){ return [..] } where [..] should correspond to your actual return code. Note the wrong position of the return type and the wrong ordering of your template arguments. 2) The fixed syntax shown in (1) should work, but it may still not realize what you are attempting to do: Your requirement was: "i need to separate codes in header and source files (for cross reference)" I'm not sure what precisely you mean with the part "(for cross reference)", but as written this implementation will only allow for instantiating the member definition *within* the translation unit where the definition has been written and you cannot realize that code attempting to instantiate this definition within a *different* translation unit will succeed, because C++ (without template export) does not support this. You either are required to make the out-of-class definition available within the other translation units (a typical way to realize that is to move the out-of-class definition in a header) or you need to provide an explicit instantiation of the corresponding template argument type combination within the separate cpp file following the definition, e.g.: template double MyClass<double>::getMyBaby(int* first, int* last); HTH & Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: SG on 4 Jun 2010 06:32
On 4 Jun., 07:41, Jun wrote: > > I found it's really difficult to work with templates in > separated source file. There are special rules for templates. You have to keep in mind that only in certain situations a compiler would actually create a specific function from a function template. Obviously, it has to know the definition to do so. So, hiding the definition in some .cpp file makes it difficult to use a specific instantiation of the function template in another .cpp file. In theory, something like this requires the use of the "export" keyword. But almost no compiler supports it. So, you're left with defining function templates in header files and including those into all the translation units that need the definitions. The one-definition-rule actually allows this. Just like in the case with inline function definitions, multiple function template definitions (in different TUs) are supported as long as they're equivalent. The linker won't complain. It'll simply remove duplicates. > For example: > > // MyClass.h > > template <class T> > struct MyClass{ > template <typename InputIterator> > T getMyBaby(InputIterator first, InputIterator last){} > }; > > How can I implement getMyBaby in separated cpp file? You can't. But you can remove the definition and create a special file for it. It just shouldn't have a cpp extension as it really is not supposed to be compiled in isolation. Here's one approach: --------8<-------- // MyClass.h template <class T> struct MyClass { template <typename InputIterator> T getMyBaby(InputIterator first, InputIterator last); }; #include "MyClass.tpp" --------8<-------- // MyClass.tpp template <class T> template <typename Iterator> T MyClass<T>::getMyBaby(Iterator first, Iterator last) { . } --------8<-------- But the only thing it buys you is a more compact header file with function template definitions isolated in another file. In terms of dependencies (some translation units still depend on this .tpp file) you really can't do any better. To be honest, I don't even know how the "export-solution" looks like. I just havn't had the chance to test a compiler that actually supports the export keyword. If I recall correctly, the "exported templates" feature has been completely removed from the latest draft of the upcoming C++ standard. It only refers to "export" as a reserved keyword that may be used in the future. So, I guess that means "exported templates" are history. Cheers, SG -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |