Invalid Template Argument?

I

Immortal Nephi

Why do I get compiler error message? It explains that I am not
allowed to create variable in the template parameter, but constant
variable is acceptable.
How can I fix the error?

c:\test_mycode.cpp(24) : error C2975: 'size' : invalid template
argument for 'Test', expected compile-time constant expression
c:\test_template.h(41) : see declaration of 'size'

// Test_Template.h

#if !defined( TEST_TEMPLATE_H )
#define TEST_TEMPLATE_H

enum Type {
Sample_Type1,
Sample_Type2
};

template< Type >
struct Traits {
};

template<>
struct Traits< Sample_Type1 > {
static const int x;
static const int y;
};

template<>
struct Traits< Sample_Type2 > {
static const int x;
static const int y;
};

template< typename T, int size >
class Test {
};

#endif // end macro !defined( TEST_TEMPLATE_H )


// Test_Template.cpp

#include "Test_Template.h"

const int Traits< Sample_Type1 >::x = 1;
const int Traits< Sample_Type1 >::y = 2;

const int Traits< Sample_Type2 >::x = 10;
const int Traits< Sample_Type2 >::y = 20;

template
class Test< int, Traits< Sample_Type1 >::x >;

template
class Test< int, Traits< Sample_Type2 >::x >;


// main.cpp

#include "Test_Template.h"

const Type type = Sample_Type1;
const int size = Traits< type >::x;

int main() {
// Test< int, size > test;
Test< int, Traits< type >::x > test2;

return 0;
}
 
I

Immortal Nephi

Try initializing your static integral consts right in their respective
class definitions (full 'Traits' template specializations), instead of
later.













Try writing

     static const int x = 1;



And here (just in case)

       static const int x = 2;

Not what I wanted, but I found another way. I made my source code to
work without compiler errors. Thanks for your tip.
 
F

Francesco S. Carta

Not what I wanted, but I found another way. I made my source code to
work without compiler errors. Thanks for your tip.

So post it here to complete the thread, and anybody getting here looking
for a solution to a similar problem will find the working code.
 
J

James Kanze

Try initializing your static integral consts right in their respective
class definitions (full 'Traits' template specializations), instead of
later.

According to the standard, that shouldn't make a difference.
(But it wouldn't surprise me if it did with some compilers.)
 
V

Victor Bazarov

According to the standard, that shouldn't make a difference.
(But it wouldn't surprise me if it did with some compilers.)

I don't speak good Standardese, so I usually rely on logic hoping that
it was present in the Committee members' minds when the Standard was
written. So, logically speaking, if I define and initialize a static
classwide const not in the class definition but elsewhere, the compiler
won't have the chance to see that value if I use the static const where
a compile-time constant expression is expected. Example:

----------------------------------- translation unit bar.cpp
struct foo { static const int size; }; // usually from a header

int bar[foo::size]; // huh?
----------------------------------- translation unit foo.cpp
struct foo { static const int size; }; // usually from a header

static const foo::size = 42;
------------------------------------------------------------

OTOH, if I do give the static some value right in the class definition,
the compiler is free to use that value (and not the member) where it
shows up in the code:

----------------------------------- translation unit bar.cpp
struct foo { static const int size = 42; }; // usually from a header

int bar[foo::size]; // success: using the *value* 42
----------------------------------- translation unit foo.cpp
struct foo { static const int size; }; // usually from a header

static const foo::size; // definition - just in case
 
J

James Kanze

On 8/17/2010 5:03 AM, James Kanze wrote:
I don't speak good Standardese, so I usually rely on logic
hoping that it was present in the Committee members' minds
when the Standard was written.

Regretfully, they don't always express themselves in standardese
as clearly as one might wish.
So, logically speaking, if I define and initialize a static
classwide const not in the class definition but elsewhere, the
compiler won't have the chance to see that value if I use the
static const where a compile-time constant expression is
expected.

Well, I think I may have misread the original code. I didn't
see that several translation units were involved. But there is
still one problem with your reasoning: I can follow it if
I initialize the constant in another translation unit, or even,
maybe after the actual use. But in the case in question, the
variable was defined and initialized before actual use in the
file. The compiler can easily see the value.
Example:

----------------------------------- translation unit bar.cpp
struct foo { static const int size; }; // usually from a header
int bar[foo::size]; // huh?

Agreed. Read strictly, the standard requires this to
work, provided foo::size is initialized with an integral
constant expression where ever it happens to be defined. I'm
pretty sure that this was not the intent, however, and no
compiler implements it.
----------------------------------- translation unit foo.cpp
struct foo { static const int size; }; // usually from a header

static const foo::size = 42;

(There's a static too many there. You meant "int const
foo::size = 42;", I'm sure.)

And here:

int bar[foo::size];

is (or should be) legal. The question becomes more interesting
if foo is a template; I think it should still be legal, but
I can imagine some compiler rejecting it, on the grounds that
the definition might have been instantiated in some other
translation unit, rather than this one.
------------------------------------------------------------
OTOH, if I do give the static some value right in the class
definition, the compiler is free to use that value (and not
the member) where it shows up in the code:
----------------------------------- translation unit bar.cpp
struct foo { static const int size = 42; }; // usually from a header
int bar[foo::size]; // success: using the *value* 42
----------------------------------- translation unit foo.cpp
struct foo { static const int size; }; // usually from a header
static const foo::size; // definition - just in case
------------------------------------------------------------
IOW, IMNSHO it *does* make a difference.

The issue isn't whether you give the static the value in the
class definition. It is whether the definition is visible, so
the compiler can see it. And this issue really only affects
templates:

template<typename T>
struct Foo
{
static int const i;
};

template<typename T>
int Foo<T>::i = 42;

int bar[Foo<int>::i];
 

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,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top