|  | template function can't be instantilized (use keyword export |  | |
| | | Ningyu Shi |  |
| Posted: Fri Aug 29, 2008 4:39 am Post subject: template function can't be instantilized (use keyword export |  |
| |  | |
I have a small demo with 5 files which describe the problem.
b.h:
#ifndef BB #define BB class B { public: template<typename T> T bf() const; }; #endif ////////////////////////// b.cpp:
#include "b.h" #include <iostream> using namespace std; template<> int B::bf<int>() const {cout << "int" << endl;return 10;} template<> double B::bf<double>() const {cout << "double" << endl;return 1.1;} /////////////////////////////// a.h:
#ifndef AA #define AA #include "b.h" class A { public: template<typename T> T a() const; private: B mb; }; #endif /////////////////////////////////// a.cpp:
#include "a.h" template<typename T> T A::a() const {return mb.bf<T>();} ////////////////////////// main.cpp
#include <iostream> #include "a.h" using namespace std; int main() { A *a = new A; a->a<double>(); return 0; }
/////////////////////// If I compile the project,
g++ a.cpp b.cpp main.cpp
I get a link error:
main.cpp:(.text+0x83): undefined reference to `double A::a<double>() const' collect2: ld returned 1 exit status
which means the A::a<double> is not instantilized. I try to use 'export' to solve this problem, but g++ doesn't support this keyword atm. If I dump all code into one file, then the problem doesn't show up. So, is there any work around other than this?
Thanks a lot. Regards Ningyu
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Alberto Ganesh Barbati |  |
| Posted: Sat Aug 30, 2008 2:40 pm Post subject: Re: template function can't be instantilized (use keyword ex |  |
| |  | |
Ningyu Shi ha scritto:
| Quote: | I have a small demo with 5 files which describe the problem.
b.h:
#ifndef BB #define BB class B { public: template<typename T> T bf() const; }; #endif ////////////////////////// b.cpp:
#include "b.h" #include <iostream using namespace std; template<> int B::bf<int>() const {cout << "int" << endl;return 10;} template<> double B::bf<double>() const {cout << "double" endl;return 1.1;} /////////////////////////////// a.h:
#ifndef AA #define AA #include "b.h" class A { public: template<typename T> T a() const; private: B mb; }; #endif /////////////////////////////////// a.cpp:
#include "a.h" template<typename T> T A::a() const {return mb.bf<T>();} ////////////////////////// main.cpp
#include <iostream #include "a.h" using namespace std; int main() { A *a = new A; a->a<double>(); return 0; }
/////////////////////// If I compile the project,
g++ a.cpp b.cpp main.cpp
I get a link error:
main.cpp:(.text+0x83): undefined reference to `double A::a<double>() const' collect2: ld returned 1 exit status
which means the A::a<double> is not instantilized. I try to use 'export' to solve this problem, but g++ doesn't support this keyword atm. If I dump all code into one file, then the problem doesn't show up. So, is there any work around other than this?
|
In absence of export, the definition of a template must be visible at the point of instantiation. This is usually achieved by moving the template definition and *all* specializations in the .h file. In your case, only the declaration of the template is visible, as the definition is inside the .cpp file.
HTH,
Ganesh
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Triple-DES |  |
| Posted: Sat Aug 30, 2008 2:46 pm Post subject: Re: template function can't be instantilized (use keyword ex |  |
| |  | |
On 29 Aug, 06:39, Ningyu Shi <ShiNin...@gmail.com> wrote:
| Quote: | I have a small demo with 5 files which describe the problem.
b.h:
#ifndef BB #define BB class B { public: template<typename T> T bf() const;};
#endif ////////////////////////// b.cpp:
#include "b.h" #include <iostream using namespace std; template<> int B::bf<int>() const {cout << "int" << endl;return 10;} template<> double B::bf<double>() const {cout << "double" endl;return 1.1;} /////////////////////////////// a.h:
#ifndef AA #define AA #include "b.h" class A { public: template<typename T> T a() const; private: B mb;};
#endif /////////////////////////////////// a.cpp:
#include "a.h" template<typename T> T A::a() const {return mb.bf<T>();} ////////////////////////// main.cpp
#include <iostream #include "a.h" using namespace std; int main() { A *a = new A; a->a<double>(); return 0;
}
/////////////////////// If I compile the project,
g++ a.cpp b.cpp main.cpp
I get a link error:
main.cpp:(.text+0x83): undefined reference to `double A::a<double>() const' collect2: ld returned 1 exit status
which means the A::a<double> is not instantilized. I try to use 'export' to solve this problem, but g++ doesn't support this keyword atm. If I dump all code into one file, then the problem doesn't show up. So, is there any work around other than this?
|
If you know exactly what types your template should be instantiated with, you can use an 'explicit instantiation directive'. However, since B::bf is 'explicitly specialized' you can not explicitly instantiate it. In that case you must put all the template code in the header file. This is how template code is usually organized (By including the .cpp file into the .h file).
I recommend reading C++ Templates: The Complete Guide, which explains template code organization. You may of course find good articles online as well. Try to google 'template inclusion model'.
Perhaps someone else could explain why you can't mix explicit instantiation and explicit specialization (14.7/5). It doesn't seem logical to me.
DP
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | annamalai |  |
| Posted: Sat Aug 30, 2008 3:15 pm Post subject: Re: template function can't be instantilized (use keyword ex |  |
| |  | |
On Aug 28, 11:39 pm, Ningyu Shi <ShiNin...@gmail.com> wrote:
| Quote: | which means the A::a<double> is not instantilized. I try to use 'export' to solve this problem, but g++ doesn't support this keyword atm. If I dump all code into one file, then the problem doesn't show up. So, is there any work around other than this?
|
One work around would be to force an instantiate of the relevant member function with the data type of interest. In your example, the following modification will work:
(begin-code)
$ cat a.h #ifndef AA #define AA #include "b.h" class A { public: template<typename T> T a() const; private: void dummy(); B mb; }; #endif $ cat a.c
#include "a.h"
template<typename T> T A::a() const {return mb.bf<T>();}
void A::dummy() { a<double>(); }
(end-code)
This is just a work around. The real solution would be to put the definition of templated member functions in the header files (in the absence of export keyword).
Rgds, anna
-- Abusive Language on Internet LINK
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Guest |  |
| Posted: Sat Aug 30, 2008 3:28 pm Post subject: Re: template function can't be instantilized (use keyword ex |  |
On Aug 29, 6:39 am, Ningyu Shi <ShiNin...@gmail.com> wrote:
| Quote: | If I compile the project,
g++ a.cpp b.cpp main.cpp
I get a link error:
main.cpp:(.text+0x83): undefined reference to `double A::a<double>() const' collect2: ld returned 1 exit status
which means the A::a<double> is not instantilized. I try to use 'export' to solve this problem, but g++ doesn't support this keyword atm. If I dump all code into one file, then the problem doesn't show up. So, is there any work around other than this?
|
You can split the code into files, but you have to #include the implementation from the header. Basically, the compiler needs to see the template implementation when the template is used.
Not necessary for B, though, since only full specializations exist.
Sebastian
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Salt_Peter |  |
| Posted: Sat Aug 30, 2008 3:28 pm Post subject: Re: template function can't be instantilized (use keyword ex |  |
| |  | |
On Aug 29, 12:39 am, Ningyu Shi <ShiNin...@gmail.com> wrote:
| Quote: | I have a small demo with 5 files which describe the problem.
b.h:
#ifndef BB #define BB class B { public: template<typename T> T bf() const;};
#endif ////////////////////////// b.cpp:
#include "b.h" #include <iostream using namespace std; template<> int B::bf<int>() const {cout << "int" << endl;return 10;} template<> double B::bf<double>() const {cout << "double" endl;return 1.1;} /////////////////////////////// a.h:
#ifndef AA #define AA #include "b.h" class A { public: template<typename T> T a() const; private: B mb;};
#endif /////////////////////////////////// a.cpp:
#include "a.h" template<typename T> T A::a() const {return mb.bf<T>();}
|
template int A::a<int>() const; template double A::a<double>() const;
see: LINK
| Quote: | ////////////////////////// main.cpp
#include <iostream #include "a.h" using namespace std; int main() { A *a = new A; a->a<double>(); return 0;
}
|
Why allocate on the heap at all? and then not release the allocation (delete a ? Why not label member functions of type A something alse than A::a()? Specially since you may be confusing the user of your code (ie:ctor A::A()).
int main() { A instance; // better: A a; instance.a<double>();
A another; another.a<int>(); }
/* double int */
| Quote: | /////////////////////// If I compile the project,
g++ a.cpp b.cpp main.cpp
I get a link error:
main.cpp:(.text+0x83): undefined reference to `double A::a<double>() const' collect2: ld returned 1 exit status
which means the A::a<double> is not instantilized. I try to use 'export' to solve this problem, but g++ doesn't support this keyword atm. If I dump all code into one file, then the problem doesn't show up. So, is there any work around other than this?
Thanks a lot. Regards Ningyu
-- [ LINK info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Bart van Ingen Schenau |  |
| Posted: Sat Aug 30, 2008 3:28 pm Post subject: Re: template function can't be instantilized (use keyword ex |  |
| |  | |
Ningyu Shi wrote:
| Quote: | I have a small demo with 5 files which describe the problem.
snip - example of separate compilation of template code /////////////////////// If I compile the project,
g++ a.cpp b.cpp main.cpp
I get a link error:
main.cpp:(.text+0x83): undefined reference to `double A::a<double>() const' collect2: ld returned 1 exit status
which means the A::a<double> is not instantilized. I try to use 'export' to solve this problem, but g++ doesn't support this keyword atm. If I dump all code into one file, then the problem doesn't show up. So, is there any work around other than this?
|
You can try to explicitly instantiate the template A::a in a.cpp, but the usual solution is to just put all the template code in the header file (either directly, or by #include of an implementation file).
export was meant as a solution for this problem, but as you noticed, it is not widely supported. And I doubt that it will ever be :-(
| Quote: | Thanks a lot. Regards Ningyu
Bart v Ingen Schenau |
-- a.c.l.l.c-c++ FAQ: LINK c.l.c FAQ: LINK c.l.c++ FAQ: LINK
[ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Jiang |  |
| Posted: Sun Aug 31, 2008 8:55 am Post subject: Re: template function can't be instantilized (use keyword ex |  |
| |  | |
On Aug 31, 12:28 am, Bart van Ingen Schenau <b...@ingen.ddns.info> wrote:
| Quote: | Ningyu Shi wrote: I have a small demo with 5 files which describe the problem.
snip - example of separate compilation of template code
/////////////////////// If I compile the project,
g++ a.cpp b.cpp main.cpp
I get a link error:
main.cpp:(.text+0x83): undefined reference to `double A::a<double>() const' collect2: ld returned 1 exit status
which means the A::a<double> is not instantilized. I try to use 'export' to solve this problem, but g++ doesn't support this keyword atm. If I dump all code into one file, then the problem doesn't show up. So, is there any work around other than this?
You can try to explicitly instantiate the template A::a in a.cpp, but the usual solution is to just put all the template code in the header file (either directly, or by #include of an implementation file).
export was meant as a solution for this problem, but as you noticed, it is not widely supported. And I doubt that it will ever be :-(
|
Actually we have at least one compiler supports export keyword. After adding export keyword to both a.h and b.h, and changing b.cpp as follows, my Comeau compiler compiles and links without any problem.
------------------------------------------------------ $ cat b.cpp #include "b.h" #include <stdio.h> #include <typeinfo> //template<> int B::bf<int>() const {return 10;} //template<> double B::bf<double>() const {return 1.1;} template<typename T> T B::bf() const{ printf("B::bf() type: %s", typeid(T).name()); return 1.1; }
$ ll *.h *.cpp -rwxr-xr-x 1 Administrator 76 Aug 31 15:41 a.cpp* -rwxr-xr-x 1 Administrator 142 Aug 31 15:43 a.h* -rwxr-xr-x 1 Administrator 271 Aug 31 15:57 b.cpp* -rwxr-xr-x 1 Administrator 106 Aug 31 15:43 b.h* -rwxr-xr-x 1 Administrator 90 Aug 31 15:50 main.cpp*
$ como --A *.cpp C++'ing a.cpp... Comeau C/C++ 4.3.10.1 (Jun 1 2008 09:39:56) for MS_WINDOWS_x86_Beta2 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict errors [microsoft] C++ noC++0x_extensions
C++'ing b.cpp... Comeau C/C++ 4.3.10.1 (Jun 1 2008 09:39:56) for MS_WINDOWS_x86_Beta2 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict errors [microsoft] C++ noC++0x_extensions
C++'ing main.cpp... Comeau C/C++ 4.3.10.1 (Jun 1 2008 09:39:56) for MS_WINDOWS_x86_Beta2 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict errors [microsoft] C++ noC++0x_extensions
$ ll aout -rwxr-xr-x 1 Administrator 81408 Aug 31 15:58 aout*
------------------------------------------------------
As my D&E(*) showed me, the support for export (by EDG) is very important because if the above support were not available, the export could be removed from the C++ standard. A proposal of removing export from C++ standard was defeated by the vote of the standard committee members(80 vs 20), because there exists at least one successful implementation for export keyword. Fortunately, or unfortunately if you think in another way, only one implementation is enough to defeat such proposal.
Also I believe icl can do the same thing because icl uses EDG frontend. For some reasons the support for export keyword was disabled. :-(
(*) The new added chapater(-1) is available @ LINK
| Quote: | Bart v Ingen Schenau
|
Jiang
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Jiang |  |
| Posted: Sun Aug 31, 2008 9:38 am Post subject: Re: template function can't be instantilized (use keyword ex |  |
| |  | |
On Aug 30, 11:40 pm, Alberto Ganesh Barbati <AlbertoBarb...@libero.it> wrote:
| Quote: | Ningyu Shi ha scritto:
I have a small demo with 5 files which describe the problem.
b.h:
#ifndef BB #define BB class B { public: template<typename T> T bf() const; }; #endif ////////////////////////// b.cpp:
#include "b.h" #include <iostream using namespace std; template<> int B::bf<int>() const {cout << "int" << endl;return 10;} template<> double B::bf<double>() const {cout << "double" endl;return 1.1;} /////////////////////////////// a.h:
#ifndef AA #define AA #include "b.h" class A { public: template<typename T> T a() const; private: B mb; }; #endif /////////////////////////////////// a.cpp:
#include "a.h" template<typename T> T A::a() const {return mb.bf<T>();} ////////////////////////// main.cpp
#include <iostream #include "a.h" using namespace std; int main() { A *a = new A; a->a<double>(); return 0; }
/////////////////////// If I compile the project,
g++ a.cpp b.cpp main.cpp
I get a link error:
main.cpp:(.text+0x83): undefined reference to `double A::a<double>() const' collect2: ld returned 1 exit status
which means the A::a<double> is not instantilized. I try to use 'export' to solve this problem, but g++ doesn't support this keyword atm. If I dump all code into one file, then the problem doesn't show up. So, is there any work around other than this?
In absence of export, the definition of a template must be visible at the point of instantiation. This is usually achieved by moving the template definition and *all* specializations in the .h file.
|
Well, even the export support is available, the above program still should not compile, because the program is ill-formed.
As we know it is not valid to have both the explicit and generated versions of a template co-exist in the same program. If declaration of the specialization does not follow the declaration of the generic template in its header file, things become subtle, especially for multi-TUs program. (b.cpp and main.cpp for this example).
For the original example, I added the necessary export keywords for both a.h and b.h, and como showed me that:
------------------------------------------------------
$ cat a.h
#ifndef AA #define AA #include "b.h" class A { public: export template<typename T> T a() const; private: B mb; };
$ cat b.h #ifndef BB #define BB class B { public: export template<typename T> T bf() const; };
#endif
$ como --A *.cpp como: Warning: COMO_MS_INCLUDE environment variable missing C++'ing a.cpp... Comeau C/C++ 4.3.10.1 (Jun 1 2008 09:39:56) for MS_WINDOWS_x86_Beta2 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict errors [microsoft] C++ noC++0x_extensions
C++'ing b.cpp... Comeau C/C++ 4.3.10.1 (Jun 1 2008 09:39:56) for MS_WINDOWS_x86_Beta2 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict errors [microsoft] C++ noC++0x_extensions
C++'ing main.cpp... Comeau C/C++ 4.3.10.1 (Jun 1 2008 09:39:56) for MS_WINDOWS_x86_Beta2 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict errors [microsoft] C++ noC++0x_extensions
C++ prelinker: T1 B::bf<T1>() const [with T1=double] no longer needed in main.obj C++ prelinker: executing: c:\ComeauCompiler\bin\como.exe --vc9 -- long_long --remark --A -c main.cpp como: Warning: COMO_MS_INCLUDE environment variable missing Comeau C/C++ 4.3.10.1 (Jun 1 2008 09:39:56) for MS_WINDOWS_x86_Beta2 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict errors [microsoft] C++ noC++0x_extensions
C++ prelinker: error: "T1 B::bf<T1>() const [with T1=double]" has been referenced as both an explicit specialization and a generated instantiation
---------------------------------------------------------
And IMHO, even export support is available, it is still better to
1. put generic template followed by declarations of the specializations within the same include file, and
2. avoid specializing templates coming from an external source
Jiang
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
|
|