Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

GNU/C++ explicit instantiation question

12 views
Skip to first unread message

Paul Wighton COOP Student

unread,
Jan 23, 2001, 4:45:22 PM1/23/01
to
Hello.

Im working on porting a project from SGI Irix to GNU Linux (Mandrake
7.2, GCC 2.95.3 19991030 (prerelease) ) and I am running into *HUGE*
template instanciation problems.

Ive given up entierly on having GCC implicitly instanciate things for
me, and decided to bite the bullet and instanciate everything myself.
The qesution is, how exactly to I go about doing this? where exactly
should I be instanciating things??

Consider this example:

************************************************
template <typename T>
class bar {
int j;
class more_foo;
};

class foo {
int i;
};

template class bar<foo>;

int main () {

}
************************************************

when compiled I get the following error:

templates.C:11: explicit instantiation of `class bar<foo>::more_foo'
before definition of template

if I move line 11 up above the class foo definitions, I get the
following error:

templates.C:7: `foo' was not declared in this scope
templates.C:7: template argument 1 is
invalid

I've tried forward defining the classes, then instanciating them, that
didnt work either. So how should I order/define/instanciate
everything??

I realise that this code will compile without the explicit
instanciation, G++ seems to handle trivial cases like this, but not more
complex ones.

It is my understanding that one common solution to this GCC
instanciation problem is to create on file with ALL required template
instanciations, then merely include that. How would I go about setting
something like that up?

Any help, even a point in the right direction would be greatly
appreciated.

Thank-you

Paul Wighton

Dietmar Kuehl

unread,
Jan 23, 2001, 5:05:57 PM1/23/01
to
Hi,
Paul Wighton COOP Student (paul.w...@nrc.ca) wrote:
: templates.C:11: explicit instantiation of `class bar<foo>::more_foo'
: before definition of template

Sure: To explicitly instantiate a template the template definition
and the definition of the template arguments have to be available.
Eg.:

template <typename T>
class foo { public: void bar(); }

template class foo<int>; // illegal: foo::bar() is not defined

template <typename T>
void foo<T>::bar() {}

template class foo<int>; // fine!

class baz;
template class foo<baz>; // illegal: baz undefined

class baz { public: bar(); };

template class foo<baz>; // fine!
--
<mailto:dietma...@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>

Paul Wighton

unread,
Jan 25, 2001, 12:58:09 PM1/25/01
to
Tanks a bunch!! it worked

Although there is still a slight problem

Say I have some code divided up between .C and .h files, with Class
definitions in the .h file, and the definitons of the members in the .C
file. When I want to use A class, I would have to #include the .C
(which of course includes the .h file as well) right?

Now lets say I want to take a set of classes and compile them into a
librbary. When I do this, and then try to link to that librbary Im back
to square 1 right?? I would have to include the corresponding .C files,
defeating the purpose of having that librbary in the first place. Is
this correct? How would I go about creating a librbary, then defining
the instanciations that I need when I link to it? Is this even
possible??

Thanks again for your help.

Ron Natalie

unread,
Jan 25, 2001, 1:36:56 PM1/25/01
to

Paul Wighton wrote:
>
> Tanks a bunch!! it worked
>
> Although there is still a slight problem
>
> Say I have some code divided up between .C and .h files, with Class
> definitions in the .h file, and the definitons of the members in the .C
> file. When I want to use A class, I would have to #include the .C
> (which of course includes the .h file as well) right?

No. It's usually a mistake to #include a .C file. That was the whole
point of separating the .h from the .C to being with. Every .C file
that uses your class needs to include the .h file. You get one copy
of each .C file per program (each is turned into a .o typically and
then gathered together by the linker).

This is pretty common accross most compile environments (the file extension
change but the behavior is the same).


>
> Now lets say I want to take a set of classes and compile them into a
> librbary.

Nope again, the .h files are used by those who want to use your library,
and the relocatable output of your compiler (the .o files) were made into
a library (.a, .lib, whatever) and they include that.

Dietmar Kuehl

unread,
Jan 25, 2001, 1:59:20 PM1/25/01
to
Hi,
Ron Natalie (r...@spamcop.net) wrote:
: No. It's usually a mistake to #include a .C file.

This statement is correct assuming a standard conforming C++ compiler.
Unfortunately, there is no such thing and if the .C contains only
template definitions it may be a reasonable workaround to include the
.C file into an appropriate file and provide eg. explicit instantiations
of the template (see the subject of this thread).

: That was the whole point of separating the .h from the .C to being
: with.

That was also a major part of the motivation to add the separation
model to the standard in the first place. At the time it was added,
people were sure they could implement it although it was known that it
will be hard. It turned out to be harder than expected and no compiler
vendor has done it yet (AFAIK).

If you have a template library, you are more or less stuck with putting
the definitions into a file which is included at least at some point.
I choose to use a separation between .h and .cc files in my
implementation of the standard library because this prepares my library
neatly for the time when the separation model is indeed supported.
Until then, it is necessary to include these files at least sometimes
to provide explicit instantiations. For classes where it is not
managable to provide all instantiations (eg. the whole STL part) the
definitions are either in the .h file or the .cc file gets included at
the end of the .h file.

: This is pretty common accross most compile environments (the file extension


: change but the behavior is the same).

Support for the separation model to handle templates like non-templates
is pretty uncommon.

r_srin...@my-deja.com

unread,
Jan 25, 2001, 3:02:13 PM1/25/01
to
may i request some additional clarifications regarding the same subject
but in the context of "indpendant functions". Let us say we have a
template :

template <class Container, class Data>
void quicksort(A container, Data* dummy) ;

i would like instantiations for list<int> and vector<float>

how would one go about create instances of "quicksort". In this case I
am attempting to create a library which I intend to use with a different
language say Ada.

thanks for any help

In article <94pt28$r9p$6...@news.BelWue.DE>,


Sent via Deja.com
http://www.deja.com/

Dietmar Kuehl

unread,
Jan 25, 2001, 3:50:44 PM1/25/01
to
Hi,
r_srin...@my-deja.com wrote:
: template <class Container, class Data>

: void quicksort(A container, Data* dummy) ;

: i would like instantiations for list<int> and vector<float>

Just instantiate the functions:

template void quicksort(std::list<int>, int*);
template void quicksort(std::vector<int>, float*);

BTW, I assume you want 'Data' to be the value type. Why don't you just
use

typedef typename Container::value_type Data;

in you template implementation?

: how would one go about create instances of "quicksort". In this case I


: am attempting to create a library which I intend to use with a different
: language say Ada.

I doubt that you can make 'std::list<int>' somehow visible to Ada on
typical platforms (I can imagine that it might work on .net but then
they seem to ignore templates...).

r_srin...@my-deja.com

unread,
Jan 26, 2001, 4:54:09 PM1/26/01
to
hmmm...

I am not sure I understand

typedef typename Container::value_type Data ;

Is it that Container::value_type indicates how the container
was "instantiated" ? I should play with this construct.

In any case, the instantiations for the functions appears to be the
same philosophy as instantiations for the template classes. Kindly
correct me if this is wrong.

You are right re list and other such stl containers. my immediate need
is only for vector but the plan was to provide my own iterators which
in turn would interface with the host iterators. (That should be
feasible !?!)

thanks


In article <94q3j4$kno$2...@news.BelWue.DE>,

Greg Comeau

unread,
Jan 26, 2001, 5:11:31 PM1/26/01
to
In article <94srlt$gr3$1...@nnrp1.deja.com>, <r_srin...@my-deja.com> wrote:
>In article <94q3j4$kno$2...@news.BelWue.DE>,
> dietma...@yahoo.com wrote:
>> r_srin...@my-deja.com wrote:
>> : template <class Container, class Data>
>> : void quicksort(A container, Data* dummy) ;
>>
>> : i would like instantiations for list<int> and vector<float>
>>
>> Just instantiate the functions:
>>
>> template void quicksort(std::list<int>, int*);
>> template void quicksort(std::vector<int>, float*);
>>
>> BTW, I assume you want 'Data' to be the value type. Why don't you just
>> use
>>
>> typedef typename Container::value_type Data;
>>
>> in you template implementation?
>>
>> : how would one go about create instances of "quicksort". In this
>> : case I am attempting to create a library which I intend to use
>> : with a different language say Ada.
>>
>> I doubt that you can make 'std::list<int>' somehow visible to Ada on
>> typical platforms (I can imagine that it might work on .net but then
>> they seem to ignore templates...).
>
>hmmm...
>
>I am not sure I understand
>
>typedef typename Container::value_type Data ;
>
>Is it that Container::value_type indicates how the container
>was "instantiated" ? I should play with this construct.

I think he's just sayint that instead of passing a second
template parameter, just use the typedef above inside the
template instead.

>In any case, the instantiations for the functions appears to be the
>same philosophy as instantiations for the template classes. Kindly
>correct me if this is wrong.

It can be.
--
Greg Comeau Comeau C/C++ 4.2.44 "so close"
ONLINE COMPILER ==> http://www.comeaucomputing.com/tryitout
com...@comeaucomputing.com http://www.comeaucomputing.com

Dietmar Kuehl

unread,
Jan 26, 2001, 5:56:18 PM1/26/01
to
Hi,
r_srin...@my-deja.com wrote:
: I am not sure I understand

: typedef typename Container::value_type Data ;

... but are implementing template? Strange! OK, here is the deal: The
standard containers internally typedef a bunch of types which is
actually a requirement on containers following the definition for
containers. Basically, an excerpt of these class templates looks like
this:

template <typename T, typname Alloc = std::allocator<T> >
class vector {
public:
typedef T value_type;
typedef T reference;
typedef size_t difference_type;
// ...
};

The same happens for all containers implementing the standard container
concept. These typedefs are extremely useful when implementing template
functions taking a "container" of some type as argument:

template <typename Cont>
void foo(Cont& cont) {
typedef typename Cont::value_type Value;
// ...
}

That is, with the above typedef I get a typedef for the value type of
the container. For example, when calling the above function with a
'std::vector<int>', the typedef 'Value' would just be 'int'. This way,
it is possible to get the value type of the container without any
support from the user.

Now, you may have seen the use of nested types in non-templates
already: these do not use the 'typename' keyword. For template
functions it is necessary to tell the compiler if a scoped name
depending on a template argument, eg. 'Cont::value_type' which depends
on the template argument 'Cont', is a type by prepending it with the
keyword 'typename'.

In total, the funky line just provides the value type of the container
without an additional dummy argument. From the code you posted and from
you question above I assume were unaware of this technique. However, it
is really useful when implementing templates...

: Is it that Container::value_type indicates how the container


: was "instantiated" ? I should play with this construct.

Yes, I think that is part of it: 'value_type' is for container
templates indeed often a template argument (however, it is not required
to be that way). The type gives some information on the template
argument, in this case the container's value type.

: In any case, the instantiations for the functions appears to be the


: same philosophy as instantiations for the template classes. Kindly
: correct me if this is wrong.

Sure, why would is be made differently...

: You are right re list and other such stl containers. my immediate need


: is only for vector but the plan was to provide my own iterators which
: in turn would interface with the host iterators. (That should be
: feasible !?!)

To interface a different language you will probably have to restrict
the interface needed to one which is understandable by a C compiler.
For example, you can probably use something like this:

extern "C" {
typedef void* int_vector;

int* int_vector_at(int_vector vec, int idx) {
return &(*static_cast<std::vector<int>*>(vec))[idx];
}

void int_vector_sort(int_vector vec) {
std::vector<int>* obj = static_cast<std::vector<int>*>(vec);
std::sort(obj->begin(), obj->end());
}

// ...
}

I doubt that you will be successful exposing template, methods, etc. to
a different language directly. You will have to put a thin C wrapper
around the stuff.

0 new messages