From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7082 invoked by alias); 26 Jul 2002 09:07:38 -0000 Mailing-List: contact gcc-help-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-help-owner@gcc.gnu.org Received: (qmail 7064 invoked from network); 26 Jul 2002 09:07:36 -0000 Received: from unknown (HELO mail.epost.de) (193.28.100.164) by sources.redhat.com with SMTP; 26 Jul 2002 09:07:36 -0000 Received: from B64a4.pppool.de (213.7.100.164) by mail.epost.de (5.5.056) (authenticated as T.Maier@epost.de) id 3D1479F0002891C7; Fri, 26 Jul 2002 11:07:36 +0200 Subject: template problems From: Thomas Maier To: gcc-help@gcc.gnu.org Cc: Thomas Maier Content-Type: multipart/mixed; boundary="=-4TPZ2IE+SSuYE8HYvaRf" Date: Fri, 26 Jul 2002 02:07:00 -0000 Message-Id: <1027675013.2062.70.camel@marvin> Mime-Version: 1.0 X-SW-Source: 2002-07/txt/msg00259.txt.bz2 --=-4TPZ2IE+SSuYE8HYvaRf Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-length: 4164 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::mapped_type mt("ext"); map::key_type kt(42); map::key_type (map::mapped_type::* key_method)() const = &map::mapped_type::size; } { typedef map 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 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 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 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 --=-4TPZ2IE+SSuYE8HYvaRf Content-Disposition: attachment; filename=small.cc Content-Transfer-Encoding: quoted-printable Content-Type: text/x-c; name=small.cc; charset=ISO-8859-15 Content-length: 1001 #include #include using namespace std; // non-member functions work template void foo(Container& container, void (*function) ()) { } // member functions don't template void foo(Container& container, void (typename Container::mapped_type::* member_f= unction)()) { } // also doesn't work template void foo(Container& container, void (MappedType::* member_function)()) { } // non-template function using map as container works void f() { { map::mapped_type mt("ext"); map::key_type kt(42); map::key_type (map::mapped_type::* key_me= thod)() const =3D &map::mapped_type::size; } { typedef map Cont; Cont::mapped_type mt("ext"); Cont::key_type kt(42); Cont::key_type (Cont::mapped_type::* key_method)() const =3D &Cont::map= ped_type::size; } } --=-4TPZ2IE+SSuYE8HYvaRf--