This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;
  }
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]