More template metaprogramming fun.... (G++/Comeau disagree)

A

Alan Woodland

I've been trying out more template metaprogramming ideas with typelists
(mostly for personal learning, I'm aware boost most probably provides
this facility already), and I've run into this small problem here.

Comeau online (without C++0x, in strict mode) accepts this example
pasted here, (apologies for the length of it). Unfortunately G++ (3.4,
4.1, 4.2) doesn't, and complains about index_find being private. The
exact error it gives is:

test.cc:21: error: 'template<class T, class N> template<class X, class
O> class typelist<T, N>::index_find' is private
test.cc:21: error: within this context

Which seems to imply I've gotten the friend declaration wrong. Is my
syntax correct for this? Can somebody point me in the direction of a
definitive answer on this one? Obviously if I make index_find public
then this whole problem goes away, but given that it's part of the
internal implementation mechanism, rather than the public interface I'd
rather keep it private, and hopefully learn which compiler is
right/wrong in this instance. I was quite surprised g++ rejected this
when Comeau accepts it.

Thanks,
Alan

#include <typeinfo>
#include <cassert>

// Utility for comparing two types
template <typename A, typename B>
class compare_types {
public:
enum { is_same = 0 };
};

// and corresponding the partial specialisation
template <typename A>
class compare_types<A,A> {
public:
enum { is_same = 1 };
};

template <typename T, typename N=void>
class typelist {
template <typename X, typename O>
class index_find;

template <typename U, typename M>
template <typename X, typename O>
friend class typelist<U,M>::index_find;
public:
typedef T type;
typedef N next;

/**
* Constant value used to indicate that a type was not found during
a search of a typelist
*/
enum { not_found=~0 };

private:
template <typename X, typename O>
class index_find {
public:
// If we are a match end recursion with a 0.
// If we aren't a match carry on recursively searching.
// If our recursive search returns failure then we should return
failure also.
enum { index=compare_types<X,T>::is_same ? 0 :
((static_cast<int>(N::template index_find<X, typename N::next>::index)
!= static_cast<int>(not_found))
? 1 + N::template index_find<X, typename N::next>::index
: not_found) };
};

template <typename X>
class index_find<X, void> {
public:
// If we are a match end recursion with a 0 index.
// If we aren't a match we can't recurse any further since we
are the tail, so propagate not_found back.
enum { index=compare_types<X,T>::is_same ? 0 : not_found };
};
public:
/**
* Use this to search to see if a typelist contains a specified
type. Returns the index
* it was (first if a type appears more than once) found at, or
not_found otherwise.
*/
template <typename X>
class index_of {
public:
enum { index=index_find<X,N>::index };
};
};

// make sure we instantiate the templates here:
int main() {
typedef typelist<float, typelist<int, typelist<char> > > list1;
assert(static_cast<int>(list1::not_found) ==
static_cast<int>(list1::index_of<double>::index));
assert(0 == static_cast<int>(list1::index_of<float>::index));
assert(1 == static_cast<int>(list1::index_of<int>::index));
assert(2 == static_cast<int>(list1::index_of<char>::index));

return 0;
}
 
C

cplusplus

Your program is pathetic try writing some better programs I tried it
out and i doesn't work very well .
if you're not serius about this then i suggest you leave this group.
I want this group to have members who are excellent in the c++
programing language okay so if you want to remain a member write a
better program.
 
M

Markus Moll

Hi

Alan said:
I've been trying out more template metaprogramming ideas with typelists
(mostly for personal learning, I'm aware boost most probably provides
this facility already), and I've run into this small problem here.

Comeau online (without C++0x, in strict mode) accepts this example
pasted here, (apologies for the length of it). Unfortunately G++ (3.4,
4.1, 4.2) doesn't, and complains about index_find being private. The
exact error it gives is:

test.cc:21: error: 'template<class T, class N> template<class X, class
O> class typelist<T, N>::index_find' is private
test.cc:21: error: within this context

Which seems to imply I've gotten the friend declaration wrong. Is my
syntax correct for this? Can somebody point me in the direction of a
definitive answer on this one? Obviously if I make index_find public
then this whole problem goes away, but given that it's part of the
internal implementation mechanism, rather than the public interface I'd
rather keep it private, and hopefully learn which compiler is
right/wrong in this instance. I was quite surprised g++ rejected this
when Comeau accepts it.

Thanks,
Alan

template <typename T, typename N=void>
class typelist {
template <typename X, typename O>
class index_find;

template <typename U, typename M>
template <typename X, typename O>
friend class typelist<U,M>::index_find;

The problem seems to be here already.
Apparently, the code should not compile, because typelist<U,M>::index_find
is not accessible within typelist<T,N>, unless T=U and N=M. Therefore, the
friend declaration is ill-formed according to 11.4(7)
There was a Defect Report about this:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#209

The other problem is, even if that was allowed, I don't see if members of
templates can be friends of templates... 14.5.3(6) explicitly talks about
non-templates only, but I might misinterpret that:
"A member of a class template may be declared to be a friend of a
non-template class."

However, GCC accepts the code if you just make other typelists friends, so

template<typename U, typename M>
friend class typelist;

I'm not sure if the code _should_ be accepted, though.

Markus
 
R

REH

Your program is pathetic try writing some better programs I tried it
out and i doesn't work very well .
if you're not serius about this then i suggest you leave this group.
I want this group to have members who are excellent in the c++
programing language okay so if you want to remain a member write a
better program.

Who are you to dictate who is allowed in this group? If we were all
*excellent* in C++, there would be no need to even have a group.
 
C

cplusplus

Listen punk i don't like your attitude show me some respect I am the
best .
You can learn alot from me so you better start sucking up to me okay .
OH by the way don't write anymore lame programs .
May be you should leave c++ programing to the best .
 
R

red floyd

cplusplus said:
Listen punk i don't like your attitude show me some respect I am the
best .
You can learn alot from me so you better start sucking up to me okay .
OH by the way don't write anymore lame programs .
May be you should leave c++ programing to the best .

Bwahahahahahahahah!!!!!!!!

Oh wait... he was serious?????

HA HA HA HA HA HA !!!!!!
 
A

Alan Woodland

template said:
The problem seems to be here already.
Apparently, the code should not compile, because typelist<U,M>::index_find
is not accessible within typelist<T,N>, unless T=U and N=M. Therefore, the
friend declaration is ill-formed according to 11.4(7)
There was a Defect Report about this:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#209

Does this imply Comeau is in error for accepting this?
The other problem is, even if that was allowed, I don't see if members of
templates can be friends of templates... 14.5.3(6) explicitly talks about
non-templates only, but I might misinterpret that:
"A member of a class template may be declared to be a friend of a
non-template class."

However, GCC accepts the code if you just make other typelists friends, so

template<typename U, typename M>
friend class typelist;

I'm not sure if the code _should_ be accepted, though.

The final paragraph of the defect report you linked to does seem to
imply that that should indeed be accepted, provided reading template
class instead of function is reasonable.

"It was observed that most of the problems involved with the current
state of affairs result from inability to declare a particular member
function as a friend; in such cases, an easy workaround is simply to
befriend the entire class rather than the specific member function."

Unfortunately it seems G++ 3.4, doesn't share this view so I think I'm
just going to have to go ahead and make index_find public against my
better judgement.

Alan
 

nmi

Joined
Jul 6, 2007
Messages
13
Reaction score
0
Is there no moderation in this group? How can be posts like those of 'cplusplus' appear here at all?
 
R

REH

Listen punk i don't like your attitude show me some respect I am the
best .
You can learn alot from me so you better start sucking up to me okay .
OH by the way don't write anymore lame programs .
May be you should leave c++ programing to the best .

I assume this is a troll to be ignored? If so, he is not a very
inventive one.

REH
 

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,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top