 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
lindahlb@hotmail.com Guest
|
Posted: Mon Mar 14, 2005 11:59 pm Post subject: Identifiers as template parameters? |
|
|
Given SomeClass:
class SomeClass {
struct Node {
SomeClass* prev;
SomeClass* next;
};
Node node1;
Node node2;
};
Is there any way to create a templated class like the following, where
the '?' in the template specification is some term that can determine
that 'name' is an identifier.
template<typename T, '?' name>
class SomeList {
public:
/* ... */
void append( T* elem ) {
elem->name.prev = mEnd;
elem->name.next = 0;
mEnd->next = elem;
elem = mEnd;
}
/* ... */
private:
T* begin;
T* end;
};
typedef SomeList<SomeClass,node1> Node1List;
typedef SomeList<SomeClass,node2> Node2List;
I'm guessing the answer is "no", but perhaps there's some clever
work-around to get the functionality I want. Otherwise, I'll have to
continue using an ugly macro work-around (which works perfectly, but
its still a macro). But man, it'd be nice to have something like this
in standard C++ (any drawbacks to such an addition?).
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
johnchx2@yahoo.com Guest
|
Posted: Tue Mar 15, 2005 3:50 pm Post subject: Re: Identifiers as template parameters? |
|
|
[email]lindahlb (AT) hotmail (DOT) com[/email] wrote:
| Quote: | Is there any way to create a templated class like the following,
where the '?' in the template specification is some term that
can determine that 'name' is an identifier.
|
Not an identifier as such, but you can accomplish what you want by
templating SomeList on a pointer-to-member. Here's a sketch:
struct SomeClass {
struct Node {
SomeClass* prev;
SomeClass* next;
};
Node node1;
Node node2;
};
template <class T, class M, M T::*MP>
struct SomeList {
void Append(T* elem)
{
M& node = elem->*MP;
node.next = 0;
// do other stuff
}
};
typedef SomeList<SomeClass, SomeClass::Node, &SomeClass::node1>
Node1List;
typedef SomeList<SomeClass, SomeClass::Node, &SomeClass::node2>
Node2List;
int main()
{
Node1List n1;
n1.Append(0);
Node2List n2;
n2.Append(0);
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Tue Mar 15, 2005 3:52 pm Post subject: Re: Identifiers as template parameters? |
|
|
<lindahlb (AT) hotmail (DOT) com> wrote...
| Quote: | Given SomeClass:
class SomeClass {
struct Node {
SomeClass* prev;
SomeClass* next;
};
Node node1;
Node node2;
};
Is there any way to create a templated class like the following, where
the '?' in the template specification is some term that can determine
that 'name' is an identifier.
template<typename T, '?' name
|
It's called "a pointer to member" and the syntax is
template
| Quote: | class SomeList {
public:
/* ... */
void append( T* elem ) {
elem->name.prev = mEnd;
|
The syntax here is a bit more complicated:
(elem->*name).prev = mEnd;
| Quote: | elem->name.next = 0;
|
Here too:
(elem->*name).next = 0;
| Quote: | mEnd->next = elem;
elem = mEnd;
}
/* ... */
private:
T* begin;
T* end;
};
typedef SomeList<SomeClass,node1> Node1List;
typedef SomeList<SomeClass,node2> Node2List;
|
The syntax here is similar:
typedef SomeList< SomeClass, &SomeClass::node1 > Node1List;
typedef SomeList< SomeClass, &SomeClass::node2 > Node2List;
(spaces are added for readability)
I may have made a mistake somewhere, but this is your general direction.
| Quote: |
I'm guessing the answer is "no", but perhaps there's some clever
work-around to get the functionality I want. Otherwise, I'll have to
continue using an ugly macro work-around (which works perfectly, but
its still a macro). But man, it'd be nice to have something like this
in standard C++ (any drawbacks to such an addition?).
|
V
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Maxim Yegorushkin Guest
|
Posted: Tue Mar 15, 2005 3:58 pm Post subject: Re: Identifiers as template parameters? |
|
|
<lindahlb (AT) hotmail (DOT) com> wrote:
| Quote: | Given SomeClass:
class SomeClass {
struct Node {
SomeClass* prev;
SomeClass* next;
};
Node node1;
Node node2;
};
Is there any way to create a templated class like the following, where
the '?' in the template specification is some term that can determine
that 'name' is an identifier.
template<typename T, '?' name
class SomeList {
public:
/* ... */
void append( T* elem ) {
elem->name.prev = mEnd;
elem->name.next = 0;
mEnd->next = elem;
elem = mEnd;
}
/* ... */
private:
T* begin;
T* end;
};
typedef SomeList<SomeClass,node1> Node1List;
typedef SomeList<SomeClass,node2> Node2List;
I'm guessing the answer is "no", but perhaps there's some clever
work-around to get the functionality I want. Otherwise, I'll have to
continue using an ugly macro work-around (which works perfectly, but
its still a macro). But man, it'd be nice to have something like this
in standard C++ (any drawbacks to such an addition?).
|
The most straightforward way to do this is to use member pointers as
template parameters:
template<typename T, typename T::Node T::*node>
struct SomeList {
void append( T* elem ) {
(elem->*node).prev = end;
(elem->*node).next = 0;
end->next = elem;
end = elem;
}
T* begin;
T* end;
};
typedef SomeList<SomeClass, &SomeClass::node1> Node1List;
typedef SomeList<SomeClass, &SomeClass::node2> Node2List;
At times one may want to avoid hardcoding the member (pointer) type at
all. The solution to this is to define names for the data members as types
and then access the members using these types. This way member's type do
not need to be hardcoded:
struct SomeClass {
struct Node {
SomeClass* prev;
SomeClass* next;
};
Node node1;
Node node2;
struct node1_tag {};
struct node2_tag {};
friend Node& get(SomeClass& t, node1_tag) { return t.node1; }
friend Node& get(SomeClass& t, node2_tag) { return t.node2; }
};
template<typename T, typename tag>
struct SomeList {
void append( T* elem ) {
get(*elem, tag()).prev = end;
get(*elem, tag()).next = 0;
end->next = elem;
end = elem;
}
T* begin;
T* end;
};
typedef SomeList<SomeClass, SomeClass::node1_tag> Node1List;
typedef SomeList<SomeClass, SomeClass::node2_tag> Node2List;
--
Maxim Yegorushkin
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
gleb.alexeev@gmail.com Guest
|
Posted: Tue Mar 15, 2005 4:02 pm Post subject: Re: Identifiers as template parameters? |
|
|
The example you posted doesn't explain your need for the feature like
this. In most cases for things like list it's better to use standard
library. However if this is just what you need, you can use something
like policies:
template<typename T, class NodeGetter>
class SomeList {
public:
/* ... */
void append( T* elem ) {
SomeClass::Node& node = NodeGetter::get(elem);
node.prev = mEnd;
node.next = 0;
mEnd->next = elem;
elem = mEnd;
}
};
struct Node1Getter {
static SomeClass::Node& get(SomeClass* elem) {
return elem->node1;
}
};
struct Node2Getter {
static SomeClass::Node& get(SomeClass* elem) {
return elem->node2;
}
};
typedef SomeList<SomeClass,Node1Getter> Node1List;
typedef SomeList<SomeClass,Node2Getter> Node2List;
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Robert Guest
|
Posted: Tue Mar 15, 2005 8:27 pm Post subject: Re: Identifiers as template parameters? |
|
|
I believe a pointer-to-member would do the trick here.
template <typename T, T::Node T::*>
class SomeList {
....
}
typedef SomeList<SomeClass, &SomeClass::node1> Node1List;
....
I haven't tried this. Take it for what it is worth.
Robert
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|