linking static template variable

G

Gernot Frisch

// - in my xy.cpp file --

template
<const int Ttex, const int Tcol, const int Tlight, int TzBuffer>
struct MyFragmentShader
{
static const int varying_count = Ttex*2 + Tcol*3 + Tlight;
};

....
template<> const int MyFragmentShader<0,1,0,1>::varying_count;
....


void foo()
{
// 'r' is of type super_complicated_class
r.fragment_shader<MyFragmentShader<0,1,0,1> >();
}
// -- ends

The result is:

undefined reference to `MyFragmentShader<0, 1, 0, 1>::varying_count'

I (try to) use GCC 4.0.2.

Can you please assist me?
 
P

Pavel Shved

// - in my xy.cpp file --

template
<const int Ttex, const int Tcol, const int Tlight, int TzBuffer>
struct MyFragmentShader
{
šstatic const int varying_count = Ttex*2 + Tcol*3 + Tlight;

};

...
template<> const int MyFragmentShader<0,1,0,1>::varying_count;
...

void foo()
{
š š// 'r' is of type super_complicated_class
š šr.fragment_shader<MyFragmentShader<0,1,0,1> >();}

// -- ends

The result is:

undefined reference to `MyFragmentShader<0, 1, 0, 1>::varying_count'

I (try to) use GCC 4.0.2.

Can you please assist me?

(Warning! Highly unreliable opinion!) well, you haven't defined value
of that specialized constant (if this way of template specialization
is ever correct), you only have declared it, so linker doesn't find it.
 
G

Gernot Frisch

(Warning! Highly unreliable opinion!) well, you haven't defined
value
of that specialized constant (if this way of template specialization
is ever correct), you only have declared it, so linker doesn't find
it.


// code----------
template
<const int Ttex, const int Tcol, const int Tlight, int TzBuffer>
struct MyFragmentShader
{
static const int varying_count = Ttex*2 + Tcol*3 + Tlight;
};

#define VARCNT(t,c,l) template<> const int
MyVertexShader<1,1,1>::attribute_count= t*2 + c*3 + l;
VARCNT(1,1,1);
VARCNT(1,1,0);
VARCNT(1,0,1);
VARCNT(1,0,0);
VARCNT(0,1,1);
VARCNT(0,1,0);
VARCNT(0,0,1);
VARCNT(0,0,0);
#undef VARCNT
// -------ends

yields:
error: duplicate initialization of MyVertexShader<1, 1,
1>::attribute_count

....I'm so, so lost here.
 
V

Victor Bazarov

Gernot said:
// code----------
template
<const int Ttex, const int Tcol, const int Tlight, int TzBuffer>
struct MyFragmentShader
{
static const int varying_count = Ttex*2 + Tcol*3 + Tlight;
};

#define VARCNT(t,c,l) template<> const int
MyVertexShader<1,1,1>::attribute_count= t*2 + c*3 + l;

So, is it 'varying_count' or 'attribute_count'?
VARCNT(1,1,1);
VARCNT(1,1,0);
VARCNT(1,0,1);
VARCNT(1,0,0);
VARCNT(0,1,1);
VARCNT(0,1,0);
VARCNT(0,0,1);
VARCNT(0,0,0);
#undef VARCNT
// -------ends

yields:
error: duplicate initialization of MyVertexShader<1, 1,
1>::attribute_count

...I'm so, so lost here.

Since you have the initialisation in the declaration (in the
class template definition), you should omit any initialisation
when defining your specialisations. That's what the compiler
is telling you here.

However, going back to your original inquiry, you need to use
your static somehow to cause the _instantiation_ of the static
member. It is likely that you didn't (at least the code you
posted didn't show any *use* of varying_count'.

Perhaps you want to repost *the actual code* that exhibits the
error...

V
 
G

Gernot Frisch

Found it, sorry for bothering!

#define VARCNT(t,c,l) \
template<> const int \
MyVertexShader<\
/* here is the bug */ \
t,c,l /* instead of 1,1,1! */ \
::attribute_count= t*2 + c*3 + l;

and one must not define the value in the declaration, then.

template
<const int Ttex, const int Tcol, const int Tlight, int TzBuffer>
struct MyFragmentShader
{
static const int varying_count; // = Ttex*2 + Tcol*3 + Tlight;
};
 
J

James Kanze

I think that's actually correct.
So, is it 'varying_count' or 'attribute_count'?

Different class template (MyVertexShader, instead of
MyFragmentShader), so why not a different name for the static.
I think he's just trying to confuse us by showing parts of two
different classes.

And is there an initializer or not in the explicit
specialization? That's very important, because as in the
original posting:
template<> const int MyFragmentShader<0,1,0,1>::varying_count;
without the initializer, this is a *declaration* of a
specialization. And as you know, an explicit specialization is
*not* a template, per se, and obeys the usual rules of
non-template declarations. Which means that if he uses it,
there'd better be one (and only one) definition in the program.
Somewhere, in a source file (not in the header), a
template<> const int

What's to be lost about. You explicitely specialize
MyVertexShader<1,1,1>::attribute_count 8 times, with different
initializers.

Again, an explicit specialization behaves pretty much like a
normal declaration. You wouldn't expect something like:

int const SomeClass::foo = 1*2 + 1*3 + 1 ;
int const SomeClass::foo = 1*2 + 1*3 + 0 ;
int const SomeClass::foo = 1*2 + 0*3 + 1 ;
int const SomeClass::foo = 1*2 + 0*3 + 0 ;
int const SomeClass::foo = 0*2 + 1*3 + 1 ;
int const SomeClass::foo = 0*2 + 1*3 + 0 ;
int const SomeClass::foo = 0*2 + 0*3 + 1 ;
int const SomeClass::foo = 0*2 + 0*3 + 0 ;

to work, and what you've written is basically the same thing.

I suspect a typo in the macro, and what you meant was:
#define VARCNT(t,c,l) template<> const int \
MyVertexShader<t,c,l>::attribute_count= t*2 + c*3 + l;
But beware: this still generates a *definition*, and not just a
declaration. Invoke your series of VARCNT in a header file,
include the header in more than one translation unit, and you'll
have multiple definitions (which the compiler isn't required to
diagnose).
Since you have the initialisation in the declaration (in the
class template definition), you should omit any initialisation
when defining your specialisations.

No. An explicit specialization replaces the template code. I
think he's confused you with his mixing two different classes
and two different problems in the same posting.
That's what the compiler is telling you here.
However, going back to your original inquiry, you need to use
your static somehow to cause the _instantiation_ of the static
member. It is likely that you didn't (at least the code you
posted didn't show any *use* of varying_count'.

If the static wasn't used, he wouldn't get an undefined
reference. The problem is that it is used, but he's explicitly
told the compiler not to instantiate the template variant,
becvause he's providing this one himself.
Perhaps you want to repost *the actual code* that exhibits the
error...

That would be nice. Preferrably in two separate postings, one
for each error.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top