Templates and typedef

R

Roger Leigh

Although I've got over most of my template-related problems, I'm
having trouble when I started to use default template parameters.
For template type T, I've typedef'd this as object_type and then
typedef'd std::vector<T> menu_list. This doesn't seem to
work though:

40 template<typename W>
41 class ObjectOptionMenuDescribeObject
42 {
43 public:
44 std::string operator () (const W& object)
45 {
46 std::eek:stringstream desc;
47 desc << object;
48 return desc.str();
49 }
50 };
51
52 template<typename T, typename D = ObjectOptionMenuDescribeObject<T> >
53 class ObjectOptionMenu : public Gtk::OptionMenu
54 {
55 public:
56 typedef T object_type;
57 typedef D description_func;
58
59 typedef std::vector<T> menu_list;
60
61 ObjectOptionMenu(const menu_list& list):
62 m_desc(),
63 m_options()
64 {
65 menu_list::const_iterator cur;
66 for (cur = list.begin();
67 cur != list.end();
68 ++cur)
69 add_item(*cur);
70 }
[...]
172 description_func m_desc;
173 menu_list m_options;
174
175 }; // class OptionMenu

[Gtk::OptionMenu is a GUI menu widget.]

When I try to compile this (just included into an empty .cc file) I
get this:

$ g++ [lots of -I options] -c test.cc
In file included from test.cc:1:
objectoptionmenu.h: In constructor `Gtkmm::ObjectOptionMenu<T,
D>::ObjectOptionMenu(const std::vector<T, std::allocator<_CharT> >&)':
objectoptionmenu.h:65: error: syntax error before `;' token

It looks like menu_list isn't defined, which gives the parse error.
This doesn't change if I change menu_list to std::vector<T>, so I
think there may be something wrong with the template definition, but I
can't see what.


When I include the same header in a real source file with lots of
other headers included as well, the error is even stranger:

In file included from posreturnsdialog.h:19,
from epicpos.cc:24:
objectoptionmenu.h: In constructor `Gtkmm::ObjectOptionMenu<T,
D>::ObjectOptionMenu(const std::vector<_Row, std::allocator<_CharT> >&)':
objectoptionmenu.h:65: error: syntax error before `;' token

Where on earth have _Row and std::allocator<_CharT> appeared from?
[_Row is a template parameter in another header, but it's not
referenced at all.] How can another unrelated template parameter
"pollute" my template? (Especially since I've not yet instantiated
it.)


Possibly related: what is the scope of the template parameter name?
Does it have to be unique to just the enclosed class/function, or all
templates declared within that scope?


Many thanks,
Roger
 
J

Jeffrey Schwab

Roger said:
Although I've got over most of my template-related problems, I'm
having trouble when I started to use default template parameters.
For template type T, I've typedef'd this as object_type and then
typedef'd std::vector<T> menu_list. This doesn't seem to
work though:

40 template<typename W>
41 class ObjectOptionMenuDescribeObject
42 {
43 public:
44 std::string operator () (const W& object)
45 {
46 std::eek:stringstream desc;
47 desc << object;
48 return desc.str();
49 }
50 };
51
52 template<typename T, typename D = ObjectOptionMenuDescribeObject<T> >
53 class ObjectOptionMenu : public Gtk::OptionMenu
54 {
55 public:
56 typedef T object_type;
57 typedef D description_func;
58
59 typedef std::vector<T> menu_list;
60
61 ObjectOptionMenu(const menu_list& list):
62 m_desc(),
63 m_options()
64 {
65 menu_list::const_iterator cur;

typename menu_list::const_iterator cur;
66 for (cur = list.begin();
67 cur != list.end();
68 ++cur)
69 add_item(*cur);
70 }
[...]
172 description_func m_desc;
173 menu_list m_options;
174
175 }; // class OptionMenu

[Gtk::OptionMenu is a GUI menu widget.]

When I try to compile this (just included into an empty .cc file) I
get this:

$ g++ [lots of -I options] -c test.cc
In file included from test.cc:1:
objectoptionmenu.h: In constructor `Gtkmm::ObjectOptionMenu<T,
D>::ObjectOptionMenu(const std::vector<T, std::allocator<_CharT> >&)':
objectoptionmenu.h:65: error: syntax error before `;' token

It looks like menu_list isn't defined, which gives the parse error.
This doesn't change if I change menu_list to std::vector<T>, so I
think there may be something wrong with the template definition, but I
can't see what.


When I include the same header in a real source file with lots of
other headers included as well, the error is even stranger:

In file included from posreturnsdialog.h:19,
from epicpos.cc:24:
objectoptionmenu.h: In constructor `Gtkmm::ObjectOptionMenu<T,
D>::ObjectOptionMenu(const std::vector<_Row, std::allocator<_CharT> >&)':
objectoptionmenu.h:65: error: syntax error before `;' token

Where on earth have _Row and std::allocator<_CharT> appeared from?
[_Row is a template parameter in another header, but it's not
referenced at all.] How can another unrelated template parameter
"pollute" my template? (Especially since I've not yet instantiated
it.)


Possibly related: what is the scope of the template parameter name?
Does it have to be unique to just the enclosed class/function, or all
templates declared within that scope?


Many thanks,
Roger
 
R

Roger Leigh

Jeffrey Schwab said:
typename menu_list::const_iterator cur;

Thanks, that works just fine!

Is it possible to declare this as a type, rather than using typename
each time?


I tried putting

typename menu_list::const_iterator;

just after the typedefs, but that doesn't work. I'd rather the users
of the class didn't need to use typename--is there any way to achieve
this?


Thanks again,
Roger
 
T

tom_usenet

Thanks, that works just fine!

Is it possible to declare this as a type, rather than using typename
each time?

You only have to use typename when using a member of a dependent type
that is also a type. So it only applies to code inside a template
definition. e.g. this is fine

ObjectOptionMenu said:
I tried putting

typename menu_list::const_iterator;

just after the typedefs, but that doesn't work.

You could add

typedef typename menu_list::const_iterator const_iterator;

and then you can use "const_iterator" instead of "typename
menu_list::const_iterator".


I'd rather the users
of the class didn't need to use typename--is there any way to achieve
this?

The users of which class? How do they use it?

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
 
M

Murray Cumming

Roger Leigh said:
52 template<typename T, typename D = ObjectOptionMenuDescribeObject<T> >
53 class ObjectOptionMenu : public Gtk::OptionMenu
54 {
55 public:
56 typedef T object_type;
57 typedef D description_func;
58
59 typedef std::vector<T> menu_list;
[snip]

I think you will like the new Gtk::ComboBox in gtkmm 2.4 which seems
to do what you want (any data types), with a model/view separation as
well.
 
R

Roger Leigh

tom_usenet said:
You only have to use typename when using a member of a dependent type
that is also a type. So it only applies to code inside a template
definition. e.g. this is fine

ObjectOptionMenu<int>::menu_list::const_iterator i;

I see.
The users of which class? How do they use it?

I wasn't aware of exactly how typename worked. This question is
wrong--I meant code using the ObjectOptionMenu<> class, but since they
don't need to use typename anyway, it's a non-issue.


For anyone else having problems with templates (and default
parameters), my working code follows:


// object-based option menu -*- C++ -*-
// $Id: objectoptionmenu.h,v 1.2 2003/12/14 16:14:54 roger Exp $
//
// Copyright (C) 2003 Roger Leigh.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////

#ifndef GTKMM_RLEXTRA_OBJECTOPTIONMENU_H
#define GTKMM_RLEXTRA_OBJECTOPTIONMENU_H

#include <cassert>
#include <iostream>
#include <map>
#include <sstream>
#include <vector>

#include <gtkmm/optionmenu.h>
#include <gtkmm/menu.h>

#include <libglademm/xml.h>

namespace Gtkmm
{
template<typename T>
class ObjectOptionMenuDescribeObject
{
public:
typedef T object_type;

std::string operator () (const object_type& object) const
{
std::eek:stringstream desc;
desc << object;
return desc.str();
}
};

template<typename T>
class ObjectOptionMenuItem : public Gtk::MenuItem
{
public:
typedef T object_type;

ObjectOptionMenuItem(const object_type& object,
const Glib::ustring& label):
Gtk::MenuItem(label),
m_object(object)
{}

virtual ~ObjectOptionMenuItem()
{}

const object_type& get_object() const
{
return m_object;
}

private:
object_type m_object;
};

template<typename T, typename D = ObjectOptionMenuDescribeObject<T> >
class ObjectOptionMenu : public Gtk::OptionMenu
{
public:
typedef T object_type;
typedef D description_func;

typedef std::vector<object_type> menu_list;

ObjectOptionMenu():
describe_object(),
m_options(),
m_menu()
{
}

ObjectOptionMenu(const menu_list& list):
describe_object(),
m_options(),
m_menu()
{
add_menu(list);
}

/**
* Constructor for initialisation from a Glade interface description.
* @param cobject the GTK+ C object.
* @param xml_interface the Glade XML interface.
*/
explicit ObjectOptionMenu(BaseObjectType* cobject,
const Glib::RefPtr<Gnome::Glade::Xml>& xml_interface):
describe_object(),
m_options(),
m_menu()
{}

virtual ~ObjectOptionMenu()
{}

void set_menu(const menu_list& list)
{
std::cerr << "ObjectOptionMenu::add_menu()" << std::endl;

remove_menu();

for (typename menu_list::const_iterator cur = list.begin();
cur != list.end();
++cur)
{
m_options.push_back(*cur);
Gtk::MenuItem *menu_item =
manage(new ObjectOptionMenuItem<object_type>(*cur, describe_object(*cur)));
m_menu.append(*menu_item);
}

Gtk::OptionMenu::set_menu(m_menu);
Gtk::OptionMenu::set_history(0);
}

void remove_menu()
{
m_options.clear();
Gtk::OptionMenu::remove_menu();
m_menu.items().clear();
}

const object_type* get_history() const
{
int selected = Gtk::OptionMenu::get_history();

const Gtk::MenuItem& menu_item = get_menu()->items()[selected];

const Gtk::MenuItem* menu_item_ptr = &menu_item;

const ObjectOptionMenuItem<object_type> *object_menu_item =
dynamic_cast<const ObjectOptionMenuItem<object_type>* >(menu_item_ptr);

if (object_menu_item != NULL)
return &object_menu_item->get_object();

return NULL;
}

void set_history(const object_type& object)
{
Gtk::MenuShell::MenuList& menu_list = get_menu()->items();
Gtk::MenuShell::MenuList::size_type size = menu_list.size();
for (Gtk::MenuShell::MenuList::size_type cur = 0;
cur < size;
++cur)
{
const Gtk::MenuItem& menu_item = menu_list[cur];
const Gtk::MenuItem* menu_item_ptr = &menu_item;

const ObjectOptionMenuItem<object_type> *object_menu_item =
dynamic_cast<const ObjectOptionMenuItem<object_type>* >(menu_item_ptr);

if (object_menu_item != NULL)
{
if (object == object_menu_item->get_object())
{
Gtk::OptionMenu::set_history(cur);
return;
}
}
}
Gtk::OptionMenu::set_history(0);
}

void on_changed()
{
std::cerr << "OptionMenu::eek:n_changed()" << std::endl;
std::cerr << " There are " << m_menu.items().size() << " items" << std::endl;
if (get_history() != NULL)
std::cerr << " Currently selected: " << describe_object(*get_history()) << std::endl;
else
std::cerr << " Nothing currently selected" << std::endl;
}

protected:
description_func describe_object;
menu_list m_options;
Gtk::Menu m_menu;

}; // class OptionMenu

}; // namespace Gtkmm


#endif // GTKMM_RLEXTRA_OBJECTOPTIONMENU_H
 

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,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top