This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
template problems
- From: Thomas Maier <T dot Maier at epost dot de>
- To: gcc-help at gcc dot gnu dot org
- Cc: Thomas Maier <T dot Maier at tu-bs dot de>
- Date: 26 Jul 2002 11:16:45 +0200
- Subject: template problems
Sorry for reposting, I forgot to attach the file small.cc.
Hi everbody,
hope this is the right mailing list. I got a problem compiling some C++
code (using "gcc version 2.95.3 20010315 (SuSE)" and also a 3.0 version,
see below). I do not know if it is valid C++ actually but I guess it
is. Question is: how can I scope deeper than level one in types used in
templates? :) Well, if you use a template that gets a container type C
as parameter, you might want to say "C::value_type some_var;" but in
order to say that you have to use typename:
typename C::value_type some_var;
That's fine. Now how can I use value_type to "scope one level deeper",
say I want to take the address of some member function of value_type:
void (C::value_type::* some_member_function)();
Just saying
void (typename C::value_type::* some_member_function)();
fails, as does saying
void (typename C::typename value_type::* some_member_function)();
Putting parens just about everywhere did not help, too. How do I have
to tell g++ to do what I want? It works in a non-template function:
void f()
{
{
map<size_t,string>::mapped_type mt("ext");
map<size_t,string>::key_type kt(42);
map<size_t,string>::key_type (map<size_t,string>::mapped_type::* key_method)() const
= &map<size_t,string>::mapped_type::size;
}
{
typedef map<size_t,string> Cont;
Cont::mapped_type mt("ext");
Cont::key_type kt(42);
Cont::key_type (Cont::mapped_type::* key_method)() const = &Cont::mapped_type::size;
}
}
The second block is the same as the first one but it uses a typedef to
make things easier to read. I wrote the first block only to see if the
typedef makes things work. I attach a small file small.cc that you can
compile.
The problem is:
/*11*/ template <class Container> void
/*12*/ foo(Container& container, void (typename Container::mapped_type::* member_function)())
/*13*/ { }
which gives
g++ -Wall -c small.cc
small.cc:12: parse error before `*'
small.cc:12: `foo' declared as function returning a function
Probably g++ doesn't know that Container::mapped_type is a type. You
even have to tell it that Container is a type, that's what that typename
is for. I tried to cheat g++ with writing
/*16*/ template <class Container, class MappedType = typename Container::mapped_type> void
/*17*/ foo(Container& container, void (MappedType::* member_function)())
/*18*/ { }
but it only said
small.cc:18: default argument for template parameter in function template `foo(Container &, void (MappedType::*)())'
(Yes, sure it is, doesn't really sound like an error. Is it one? In
the Stroustrup there is an example with default arguments so I expected
it to work.)
I also tried all that with "gcc version 3.0.1 (SuSE)". Doesn't work.
Unfortunately I am not able to just download and install the latest gcc
version to see if things work as I only have a very slow dial up
connection (and here in Germany they charge for connection *times*!
pfff...). And unexperienced as I am that would probably make things
even worse :). So is this a problem with g++ or with my understanding
of or my way of writing down C++? And if it is the former, is it fixed
in 3.1 or will it be fixed in 3.2? And please be so kind and cc any
follow-ups to me as I am not on this list (because of said f!$%&ing slow
modem :).
Regards and advTHANKSance, Thomas.
P.S.: Just in case you wonder why the hell I need this: Actually I
wanted to write an assoc_insert_iterator to insert a value into a map
like a back_inserter (gives a back_insert_iterator that) inserts into a
list, for example. The iterator needs to be parameterized with some X
where it can get the value's key from. Basically when I write
(simplified pseudo code)
map<Key, Value> m;
fill(assoc_inserter(m, X));
and fill(assoc_insert_iterator iter) calls iter's operator=, operator=
has to call some method or function "Key X(Value)" that I gave as a
parameter.
Specifying functions works, see above. But when I want to pass a method
(exploiting the fact that some classes have some method giving a
key-function) it doesn't, see above.
--
Thomas Maier <T.Maier@tu-bs.de>
#include<string>
#include<map>
using namespace std;
// non-member functions work
template <class Container> void
foo(Container& container, void (*function) ())
{ }
// member functions don't
template <class Container> void
foo(Container& container, void (typename Container::mapped_type::* member_function)())
{ }
// also doesn't work
template <class Container, class MappedType = typename Container::mapped_type> void
foo(Container& container, void (MappedType::* member_function)())
{ }
// non-template function using map as container works
void f()
{
{
map<size_t,string>::mapped_type mt("ext");
map<size_t,string>::key_type kt(42);
map<size_t,string>::key_type (map<size_t,string>::mapped_type::* key_method)() const
= &map<size_t,string>::mapped_type::size;
}
{
typedef map<size_t,string> Cont;
Cont::mapped_type mt("ext");
Cont::key_type kt(42);
Cont::key_type (Cont::mapped_type::* key_method)() const = &Cont::mapped_type::size;
}
}