Invalid template argument

K

Kevin Grigorenko

Hello all,

Okay, I've got a templated class that that takes an int and a char *, but
when I try to instantiate an object of that template, VS.NET complains with:

error C2975: 'S' : invalid template argument for 'TextDB::TextDB_Version',
constant expression expected

template<int N, char *S>
class TextDB_Version
{
[...]
};

#define TDB_DEFAULT_DELIMITER "."
class TextDB
{
private:
TextDB_Version<3, TDB_DEFAULT_DELIMITER> myVersion;
};

I can't understand what's wrong with this. It seems to me from
documentation that I should be able to use char *'s as literal template
arguments, what am I missing here? I tried taking out the #define and put
in just a string there, TextDB_Version<3, "."> myVersion; and that had the
same error obviously.

Thanks for everyone's time,
Kevin Grigorenko
 
T

tom_usenet

Hello all,

Okay, I've got a templated class that that takes an int and a char *, but
when I try to instantiate an object of that template, VS.NET complains with:

error C2975: 'S' : invalid template argument for 'TextDB::TextDB_Version',
constant expression expected

template<int N, char *S>
class TextDB_Version
{
[...]
};

#define TDB_DEFAULT_DELIMITER "."
class TextDB
{
private:
TextDB_Version<3, TDB_DEFAULT_DELIMITER> myVersion;
};

I can't understand what's wrong with this. It seems to me from
documentation that I should be able to use char *'s as literal template
arguments, what am I missing here? I tried taking out the #define and put
in just a string there, TextDB_Version<3, "."> myVersion; and that had the
same error obviously.

Literals don't have external linkage, but template parameters must. So
you need:

char* TDB_DEFAULT_DELIMITER = "."; //has external linkage.

class TextDB
{
private:
TextDB_Version<3, TDB_DEFAULT_DELIMITER> myVersion;
};

Tom
 
W

White Wolf

tom_usenet said:
error C2975: 'S' : invalid template argument for
'TextDB::TextDB_Version', constant expression expected
[SNIP]
Literals don't have external linkage, but template parameters must. So
you need:

char* TDB_DEFAULT_DELIMITER = "."; //has external linkage.

Is that really a compile time constant (required for template
instantiation)?
 
K

Kevin Saff

Kevin Grigorenko said:
Hello all,

SNIP

I can't understand what's wrong with this. It seems to me from
documentation that I should be able to use char *'s as literal template
arguments, what am I missing here? I tried taking out the #define and put
in just a string there, TextDB_Version<3, "."> myVersion; and that had the
same error obviously.

This is addressed many times in the archives (but not in the FAQ yet, it
appears). I'm sure you can search google groups for the long answer. The
short answer is char* is fine for template arguments, but you just can't
create templates of the form TemplateClass<"text">. In this particular
case, why don't you just declare your template as:

template<int N, char S>
class TextDB_Version
{
[...]
};

and then you can instantiate with

TextDB_Version<3, '.'>
 
G

Gianni Mariani

tom_usenet said:
..
....


Literals don't have external linkage, but template parameters must. So
you need:

char* TDB_DEFAULT_DELIMITER = "."; //has external linkage.

class TextDB
{
private:
TextDB_Version<3, TDB_DEFAULT_DELIMITER> myVersion;
};

Tom

The alternative is to use a single char as a delimiter:

template<int N, char D>

like:

TextDB_Version<3, '.'>

if you only have single character delimiters.
 
K

Kevin Grigorenko

Kevin Saff said:
Kevin Grigorenko said:
Hello all,

SNIP

I can't understand what's wrong with this. It seems to me from
documentation that I should be able to use char *'s as literal template
arguments, what am I missing here? I tried taking out the #define and put
in just a string there, TextDB_Version<3, "."> myVersion; and that had the
same error obviously.

This is addressed many times in the archives (but not in the FAQ yet, it
appears). I'm sure you can search google groups for the long answer. The
short answer is char* is fine for template arguments, but you just can't
create templates of the form TemplateClass<"text">. In this particular
case, why don't you just declare your template as:

template<int N, char S>
class TextDB_Version
{
[...]
};

and then you can instantiate with

TextDB_Version<3, '.'>

I'm sorry about being a little bit oblivious, but where are the archives? I
will use this suggestion however and just use one character.

The interesting thing is that in the description of the error, VS.NET gives
this as an example of how to fix it:

// C2975.cpp
template <char *P>
class x
{
char * f()
{
return P;
}
};

x<"abc"> *p = 0; // C2975 addr of object with internal linkage

Is this standardized? Does it have something to do with "internal linkage,"
which i must say i'm also oblivious about.

Thanks again,
Kevin Grigorenko
 
K

Kevin Saff

Kevin Grigorenko said:
I'm sorry about being a little bit oblivious, but where are the archives? I
will use this suggestion however and just use one character.

Sorry, here's a link:
http://groups.google.com/groups?q=comp.lang.c++

and here are some posts you may be interested in:
http://groups.google.com/groups?hl=en&q=template+char*&meta=group=comp.lan
g.c%252B%252B.*

The interesting thing is that in the description of the error, VS.NET gives
this as an example of how to fix it:

// C2975.cpp
template <char *P>
class x
{
char * f()
{
return P;
}
};

x<"abc"> *p = 0; // C2975 addr of object with internal linkage

Is this standardized? Does it have something to do with "internal linkage,"
which i must say i'm also oblivious about.

That looks like just an example of the error, rather than a fix. They're
constructing a null pointer to a x<"abc"> object, but "abc" has internal
linkage so isn't eligible for use as a template parameter.

Internal linkage means the variable name can't be accessed in external
compilation units. For one thing, note that x<"abc"> would at least
represent a different class in a different compilation unit, because the
address of the string will be different. This means at best the template
class would have internal linkage as well. Still it seems like there could
be use for such a thing; apparently the full reason template parameters
cannot have internal linkage has something to do with how template names are
required to be mangled.
 
T

tom_usenet

tom_usenet said:
error C2975: 'S' : invalid template argument for
'TextDB::TextDB_Version', constant expression expected
[SNIP]
Literals don't have external linkage, but template parameters must. So
you need:

char* TDB_DEFAULT_DELIMITER = "."; //has external linkage.

Is that really a compile time constant (required for template
instantiation)?

Whoops, that was meant to be:

char TDB_DEFAULT_DELIMITER[] = "."; //has external linkage.

Tom
 

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,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top