By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,470 Members | 1,068 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,470 IT Pros & Developers. It's quick & easy.

How to you access a nested template class?

P: n/a
Hi all,

I'm a bit confused about the syntax used to access a nested template
class. Essentially I have a bunch of class types to represent different
types of records in a database, and I want to store some cache data for
each datatype. The simplified code below demonstrates my issue - I
think I understand why it doesn't work as is (the structure only
declares the storage, I need to instantiate it for each template type)
but I'm not sure how to actually go about doing that.

Any pointers would be appreciated!

Thanks,
Adam.
class RecordTypeA { };
class RecordTypeB { };

class Main {

private:

template <typename T>
struct CacheData {
int i;
};

public:

template <typename T>
void set(T t, int x)
{
// Store some type-specific data for record type T
this->CacheData<T>::i = x;
}

};

int main(void)
{
RecordTypeA A;
RecordTypeB B;
Main m;
m.set(A, 1);
m.set(B, 2);

// At this point, I want this to be the case:
// m.CacheData<A>::i == 1
// m.CacheData<B>::i == 2

return 0;
}
Nov 19 '07 #1
Share this Question
Share on Google+
9 Replies


P: n/a
Adam Nielsen wrote:
Hi all,

I'm a bit confused about the syntax used to access a nested template
class. Essentially I have a bunch of class types to represent different
types of records in a database, and I want to store some cache data for
each datatype. The simplified code below demonstrates my issue - I
think I understand why it doesn't work as is (the structure only
declares the storage, I need to instantiate it for each template type)
but I'm not sure how to actually go about doing that.

Any pointers would be appreciated!

Thanks,
Adam.
class RecordTypeA { };
class RecordTypeB { };

class Main {

private:

template <typename T>
struct CacheData {
int i;
};
This declares a type.
>
public:

template <typename T>
void set(T t, int x)
{
// Store some type-specific data for record type T
this->CacheData<T>::i = x;
There is no member variable this->CacheData<Tsince CacheData<Tis a type.
}

};

int main(void)
{
RecordTypeA A;
RecordTypeB B;
Main m;
m.set(A, 1);
You cannot call set that way. Templates do not make types into valid
arguments for functions.
m.set(B, 2);

// At this point, I want this to be the case:
// m.CacheData<A>::i == 1
// m.CacheData<B>::i == 2

return 0;
}

You may want to ponder about the following:
#include <cassert>
#include <map>

template < typename T >
class typemap {

typedef void (*id) ( void );

template < typename A >
static
void type_identifier ( void ) {}

std::map< id, T data;

public:

template < typename A >
T const & value ( void ) const {
return ( data[ &type_identifier<A] );
}

template < typename A >
T & value ( void ) {
return ( data[ &type_identifier<A] );
}

};

int main ( void ) {
typemap<inttable;
table.value<char>() = 2;
table.value<int>() = 1;
assert( table.value<char>() == 2 );
assert( table.value<int>() == 1 );
}

Best

Kai-Uwe Bux

Nov 19 '07 #2

P: n/a
You may want to ponder about the following:
>

#include <cassert>
#include <map>

template < typename T >
class typemap {

typedef void (*id) ( void );

template < typename A >
static
void type_identifier ( void ) {}

std::map< id, T data;

public:

template < typename A >
T const & value ( void ) const {
return ( data[ &type_identifier<A] );
}

template < typename A >
T & value ( void ) {
return ( data[ &type_identifier<A] );
}

};

int main ( void ) {
typemap<inttable;
table.value<char>() = 2;
table.value<int>() = 1;
assert( table.value<char>() == 2 );
assert( table.value<int>() == 1 );
}
That makes sense, thanks for the example! Out of curiosity, is there
any way of doing this without using a runtime lookup? Something like a
'template-variable', if there were such a thing.

Cheers,
Adam.
Nov 20 '07 #3

P: n/a
Adam Nielsen wrote:
>You may want to ponder about the following:
#include <cassert>
#include <map>

template < typename T >
class typemap {

typedef void (*id) ( void );

template < typename A >
static
void type_identifier ( void ) {}

std::map< id, T data;

public:

template < typename A >
T const & value ( void ) const {
return ( data[ &type_identifier<A] );
}

template < typename A >
T & value ( void ) {
return ( data[ &type_identifier<A] );
}

};

int main ( void ) {
typemap<inttable;
table.value<char>() = 2;
table.value<int>() = 1;
assert( table.value<char>() == 2 );
assert( table.value<int>() == 1 );
}

That makes sense, thanks for the example! Out of curiosity, is there
any way of doing this without using a runtime lookup? Something like a
'template-variable', if there were such a thing.
You can do this for static data (e.g., you can have such data on a per class
basis):

#include <cassert>

template < typename T >
struct static_typemap {

template < typename A >
static
T & value ( void ) {
static T data;
return ( data );
}

};
int main ( void ) {

static_typemap<int>::value<char>() = 1;
static_typemap<int>::value<int>() = 2;

assert( static_typemap<int>::value<char>() == 1 );
assert( static_typemap<int>::value<int>() == 2 );

}
_If_ we had templated virtual member functions, we could do such tricks on a
per object basis (and all sorts of other cool stuff).
Best

Kai-Uwe Bux
Nov 20 '07 #4

P: n/a
You may want to ponder about the following:
>

#include <cassert>
#include <map>

template < typename T >
class typemap {

typedef void (*id) ( void );

template < typename A >
static
void type_identifier ( void ) {}

std::map< id, T data;

public:

template < typename A >
T const & value ( void ) const {
return ( data[ &type_identifier<A] );
}

template < typename A >
T & value ( void ) {
return ( data[ &type_identifier<A] );
}

};

int main ( void ) {
typemap<inttable;
table.value<char>() = 2;
table.value<int>() = 1;
assert( table.value<char>() == 2 );
assert( table.value<int>() == 1 );
}
Hi Kai-Uwe,

I've just started implementing this design in my code, but I can't
figure out why it won't work inside a template.

For example, if I delete your main() function above and replace the code
with this:

template <typename X>
int m ( void ) {
typemap<inttable;
table.value<char>() = 2; // line 59 in the error below
table.value<int>() = 1;
assert( table.value<char>() == 2 );
assert( table.value<int>() == 1 );
}

int main ( void ) {
m<int>();
}

When I compile it I end up with this:

t4.cpp: In function `int m()':
t4.cpp:59: error: parse error before `>' token
t4.cpp:60: error: parse error before `>' token
t4.cpp:61: error: parse error before `>' token
t4.cpp:62: error: parse error before `>' token

I don't understand why this happens, as I didn't think it mattered
*where* you used the code. Is there something special you must do in
this situation?

Thanks again,
Adam.
Nov 28 '07 #5

P: n/a
Adam Nielsen wrote:
>You may want to ponder about the following:
#include <cassert>
#include <map>

template < typename T >
class typemap {

typedef void (*id) ( void );

template < typename A >
static
void type_identifier ( void ) {}

std::map< id, T data;

public:

template < typename A >
T const & value ( void ) const {
return ( data[ &type_identifier<A] );
}

template < typename A >
T & value ( void ) {
return ( data[ &type_identifier<A] );
}

};

int main ( void ) {
typemap<inttable;
table.value<char>() = 2;
table.value<int>() = 1;
assert( table.value<char>() == 2 );
assert( table.value<int>() == 1 );
}

Hi Kai-Uwe,

I've just started implementing this design in my code, but I can't
figure out why it won't work inside a template.

For example, if I delete your main() function above and replace the code
with this:

template <typename X>
int m ( void ) {
typemap<inttable;
table.value<char>() = 2; // line 59 in the error below
table.value<int>() = 1;
assert( table.value<char>() == 2 );
assert( table.value<int>() == 1 );
}

int main ( void ) {
m<int>();
}

When I compile it I end up with this:

t4.cpp: In function `int m()':
t4.cpp:59: error: parse error before `>' token
t4.cpp:60: error: parse error before `>' token
t4.cpp:61: error: parse error before `>' token
t4.cpp:62: error: parse error before `>' token

I don't understand why this happens, as I didn't think it mattered
*where* you used the code. Is there something special you must do in
this situation?
I cannot reproduce the error. The code you posted compiles for me. This
maybe due to you giving instructions on how to create the code from the
present pieces instead of posting a complete piece.
Best

Kai-Uwe Bux
Nov 28 '07 #6

P: n/a
I cannot reproduce the error. The code you posted compiles for me. This
maybe due to you giving instructions on how to create the code from the
present pieces instead of posting a complete piece.
That's strange then - well here is the exact code I'm compiling.
Perhaps if someone else using GCC can test it as well to see whether
it's a compiler issue?

#include <cassert>
#include <map>

template < typename T >
class typemap {

typedef void (*id) ( void );

template < typename A >
static
void type_identifier ( void ) {}

std::map< id, T data;

public:

template < typename A >
T const & value ( void ) const {
return ( data[ &type_identifier<A] );
}

template < typename A >
T & value ( void ) {
return ( data[ &type_identifier<A] );
}

};

template <typename X>
int m ( void ) {
typemap<inttable;
table.value<char>() = 2;
table.value<int>() = 1;
assert( table.value<char>() == 2 );
assert( table.value<int>() == 1 );
}

int main ( void ) {
m<int>();
}

$ g++ -o t t.cpp
t.cpp: In function `int m()':
t.cpp:32: syntax error before `>' token
t.cpp:33: syntax error before `>' token
t.cpp:34: syntax error before `>' token
t.cpp:35: syntax error before `>' token
$ g++ --version
g++-gcc-3.2.3 (GCC) 3.2.3

I've also tried it with GCC 3.3.4 with the same result.

Cheers,
Adam.
Nov 28 '07 #7

P: n/a
Adam Nielsen wrote:
>I cannot reproduce the error. The code you posted compiles for me. This
maybe due to you giving instructions on how to create the code from the
present pieces instead of posting a complete piece.

That's strange then - well here is the exact code I'm compiling.
Perhaps if someone else using GCC can test it as well to see whether
it's a compiler issue?
[code snipped]
I've also tried it with GCC 3.3.4 with the same result.
Thanks for the complete code. It compiles for me with g++ (gcc 3.4.6 and
4.1.1).
Best

Kai-Uwe Bux
Nov 28 '07 #8

P: n/a
On Nov 28, 12:56 pm, Adam Nielsen
<adam.niel...@remove.this.uq.edu.auwrote:
I cannot reproduce the error. The code you posted compiles
for me. This maybe due to you giving instructions on how to
create the code from the present pieces instead of posting a
complete piece.
That's strange then - well here is the exact code I'm
compiling. Perhaps if someone else using GCC can test it as
well to see whether it's a compiler issue?
#include <cassert>
#include <map>
template < typename T >
class typemap {
typedef void (*id) ( void );
template < typename A >
static
void type_identifier ( void ) {}
std::map< id, T data;
public:
template < typename A >
T const & value ( void ) const {
return ( data[ &type_identifier<A] );
}
template < typename A >
T & value ( void ) {
return ( data[ &type_identifier<A] );
}
};
template <typename X>
int m ( void ) {
typemap<inttable;
table.value<char>() = 2;
table.value<int>() = 1;
assert( table.value<char>() == 2 );
assert( table.value<int>() == 1 );
}
int main ( void ) {
m<int>();
}
$ g++ -o t t.cpp
t.cpp: In function `int m()':
t.cpp:32: syntax error before `>' token
t.cpp:33: syntax error before `>' token
t.cpp:34: syntax error before `>' token
t.cpp:35: syntax error before `>' token
$ g++ --version
g++-gcc-3.2.3 (GCC) 3.2.3
I've also tried it with GCC 3.3.4 with the same result.
I get the same errors with 3.2.3, but it compiles with g++
4.1.0. If you replace typemap<intwith typemap<Xin the first
line of m, you get errors with both compilers, of course.
Changing each of the function calls to:

table.template value<...>...

works in all cases however.

It's an interesting case, since it's the only case I know of off
hand in which a (non-instantiated) template definition can
trigger the instantiation of another template. Apparently, g++
pre-4.0 is not instantiating typemap<inthere, and so is
treating the < as if it were the less than operator. (Note that
in the case of typemap<X>, the context is dependent, so you are
required to tell the compiler when the name in question -- here,
value -- is a type or a template.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 29 '07 #9

P: n/a
Changing each of the function calls to:
>
table.template value<...>...

works in all cases however.
Ah, that's excellent - that's saved me a compiler upgrade :-)

Cheers,
Adam.
Nov 30 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.