Creating table of const ptr to member funcs

  • Thread starter Thomas Matthews
  • Start date
T

Thomas Matthews

Hi,

How do I create a const table of pointers to member functions?
I'm implementing a Factory pattern (or jump table). I want to
iterate through the table, calling each member function until
a non-zero index is returned. Below is my attempt, which
generates compiler errors:

namespace Reference
{
class Base
{
};
}

class My_Class
{
public:
typedef int (My_Class:: * P_ADD_REC_FUNC)
(const Reference::Base& ref);
int add_reference(const Reference::Base& ref);

private:
int add_book(const Reference::Base& ref);
int add_magazine(const Reference::Base& ref);
const P_ADD_REC_FUNC add_func_table[];
};

//[1] The following definition generates the errors.
const P_ADD_REC_FUNC My_Class::add_func_table[] =
{
add_book, add_magazine
};
static const unsigned int NUM_ADD_FUNCS =
sizeof(add_func_table) / sizeof(add_func_table[0]);

int
My_Class ::
add_book(const Reference::Base& ref)
{
// Stubbed for now.
return 0;
}

int
My_Class ::
add_magazine(const Reference::Base& ref)
{
// Stubbed for now.
return 1;
}


int
My_Class ::
add_reference(const Reference::Base& ref)
{
int id(0);
for (unsigned int i = 0;
(id == 0) && (i < NUM_ADD_FUNCS);
++i)
{
id = add_func_table(ref);
}
return id;
}

The error that I am getting is:
Multiple declaration for "My_Class::add_func_table"

In the past I would use a table of pointers to
static member functions. This time I thought I
would change content of the table to use pointers
to {non-static} member functions since I am referring
to the table within the same class.

So, how should I be declaring a constant table of
pointers to member functions?

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
http://www.sgi.com/tech/stl -- Standard Template Library
 
R

Rob Williscroft

Thomas Matthews wrote in
In the past I would use a table of pointers to
static member functions. This time I thought I
would change content of the table to use pointers
to {non-static} member functions since I am referring
to the table within the same class.

So, how should I be declaring a constant table of
pointers to member functions?

See comments inline.

namespace Reference
{
class Base
{
};
}

class My_Class
{
public:
typedef
int (My_Class:: * const P_ADD_REC_FUNC_CONST)
(Reference::Base const& ref)
;
int add_reference(const Reference::Base& ref);

private:
int add_book(Reference::Base const& ref);
int add_magazine(Reference::Base const & ref);

// Note static and new typedef
static P_ADD_REC_FUNC_CONST add_func_table[];

public:
static const unsigned int NUM_ADD_FUNCS;
};

//addition of My_Class::
My_Class::p_ADD_REC_FUNC_CONST My_Class::add_func_table[] =
{
&My_Class::add_book, &My_Class::add_magazine
};

//Now a member
unsigned int const My_Class::NUM_ADD_FUNCS =
sizeof(My_Class::add_func_table)
/
sizeof(My_Class::add_func_table[0])
;

int
My_Class ::
add_book(const Reference::Base& ref)
{
return 0;
}

int
My_Class ::
add_magazine(const Reference::Base& ref)
{
return 1;
}


int
My_Class ::
add_reference(const Reference::Base& ref)
{
int id(0);
for (unsigned int i = 0;
(id == 0) && (i < My_Class::NUM_ADD_FUNCS);
++i)
{
// Need to use ->*
id = (this->*add_func_table)(ref);
}
return id;
}

int main()
{
}

HTH

Rob.
 
D

DarkSpy

在 Sun, 02 Nov 2003 20:41:19 GMT 时, Thomas Matthews
Hi,

How do I create a const table of pointers to member functions?
I'm implementing a Factory pattern (or jump table). I want to
iterate through the table, calling each member function until
a non-zero index is returned. Below is my attempt, which
generates compiler errors:

namespace Reference
{
class Base
{
};
}

class My_Class
{
public:
typedef int (My_Class:: * P_ADD_REC_FUNC)
(const Reference::Base& ref);
int add_reference(const Reference::Base& ref);

private:
int add_book(const Reference::Base& ref);
int add_magazine(const Reference::Base& ref);
const P_ADD_REC_FUNC add_func_table[];
};

//[1] The following definition generates the errors.
const P_ADD_REC_FUNC My_Class::add_func_table[] =
{
add_book, add_magazine
};
static const unsigned int NUM_ADD_FUNCS =
sizeof(add_func_table) / sizeof(add_func_table[0]);

i'm now find a way to do this, but i do not know is this you want,
code:
class My_Class
{
public:
typedef int (My_Class:: * P_ADD_REC_FUNC)(const Reference::Base&
ref);
int add_reference(const Reference::Base& ref);

private:
int add_book(const Reference::Base& ref);
int add_magazine(const Reference::Base& ref);
//static const P_ADD_REC_FUNC add_func_table[];
// const P_ADD_REC_FUNC add_func_table[];
//change to :
const P_ADD_REC_FUNC * add_func_table;

// and add the constructor like this:
My_Class(const P_ADD_REC_FUNC ptr_to[]) : add_func_table(ptr_to) {}
};
 
T

Thomas Matthews

Rob said:
Thomas Matthews wrote in
In the past I would use a table of pointers to
static member functions. This time I thought I
would change content of the table to use pointers
to {non-static} member functions since I am referring
to the table within the same class.

So, how should I be declaring a constant table of
pointers to member functions?


See comments inline.

namespace Reference
{
class Base
{
};
}

class My_Class
{
public:
typedef
int (My_Class:: * const P_ADD_REC_FUNC_CONST)
(Reference::Base const& ref)
;
int add_reference(const Reference::Base& ref);

private:
int add_book(Reference::Base const& ref);
int add_magazine(Reference::Base const & ref);

// Note static and new typedef
static P_ADD_REC_FUNC_CONST add_func_table[];

public:
static const unsigned int NUM_ADD_FUNCS;
};

//addition of My_Class::
My_Class::p_ADD_REC_FUNC_CONST My_Class::add_func_table[] =
{
&My_Class::add_book, &My_Class::add_magazine
};

//Now a member
unsigned int const My_Class::NUM_ADD_FUNCS =
sizeof(My_Class::add_func_table)
/
sizeof(My_Class::add_func_table[0])
;

int
My_Class ::
add_book(const Reference::Base& ref)
{
return 0;
}

int
My_Class ::
add_magazine(const Reference::Base& ref)
{
return 1;
}


int
My_Class ::
add_reference(const Reference::Base& ref)
{
int id(0);
for (unsigned int i = 0;
(id == 0) && (i < My_Class::NUM_ADD_FUNCS);
++i)
{
// Need to use ->*
id = (this->*add_func_table)(ref);
}
return id;
}

int main()
{
}

HTH

Rob.


Thanks for the suggestion. I've tried it and it worked.
However, I was hoping for a "const" table rather than
a static one.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
R

Rob Williscroft

Thomas Matthews wrote in @newssvr31.news.prodigy.com:
Thanks for the suggestion. I've tried it and it worked.
However, I was hoping for a "const" table rather than
a static one.

This should be possible, I put static in because of this initializer:
const P_ADD_REC_FUNC My_Class::add_func_table[] =
{
add_book, add_magazine
};

What role is "const" fulfilling. The above suggested to me that you
wanted a fixed table, since you say you don't want a static member
table, I guess you want to be able to create several My_Class
objects, all with different tables.

Perhapse a member with type std::vector< P_ADD_REC_FUNC_CONST >
would be a good place to start, or maybe:

struct My_Class
{
typedef
int (My_Class:: * const P_ADD_REC_FUNC_CONST)
(Reference::Base const& ref)
;

My_Class( P_ADD_REC_FUNC_CONST *table, std::size_t count ) :
add_fun_table( table ), add_fun_table_count( count )
{}

P_ADD_REC_FUNC_CONST * const add_func_table;
std::size_t const add_fun_table_count;

int add_book(Reference::Base const& ref);
int add_magazine(Reference::Base const & ref);
};



My_Class::p_ADD_REC_FUNC_CONST global[] = {
{ &My_Class::add_book, &My_Class::add_magazine }
};


My_Class my_instance( global, 2 );

If you could give a simple usage scenario for My_Class it might help.

Rob.
 
T

Thomas Matthews

Rob said:
Thomas Matthews wrote in @newssvr31.news.prodigy.com:

Thanks for the suggestion. I've tried it and it worked.
However, I was hoping for a "const" table rather than
a static one.


This should be possible, I put static in because of this initializer:

const P_ADD_REC_FUNC My_Class::add_func_table[] =
{
add_book, add_magazine
};


What role is "const" fulfilling. The above suggested to me that you
wanted a fixed table, since you say you don't want a static member
table, I guess you want to be able to create several My_Class
objects, all with different tables.


If you could give a simple usage scenario for My_Class it might help.

Rob.

In the big picture, "My_Class" is a singleton interface to a database
of references. There are many relational tables to contain the data.
I'm using the interface to store a reference into the database (thus
the "add_*" methods) and to create references from the database.

I was hoping to have a const table of pointers to member functions
because the pointers to the functions would not change (constant
data). The quantity of pointers also doesn't change. Thus the
requirement for a constant table.

Every reference has a name and a category. The category is used
to determine which table the data is stored in. For example, the
data for a "Book" reference would be placed into the book table,
and the data for a "Magazine" reference would be placed into the
magazine table. Instead of having one public "add_" method for
each category, I'm using one public method for the base class.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
R

Rob Williscroft

Thomas Matthews wrote in @newssvr33.news.prodigy.com:
In the big picture, "My_Class" is a singleton interface to a database
of references. There are many relational tables to contain the data.
I'm using the interface to store a reference into the database (thus
the "add_*" methods) and to create references from the database.

I was hoping to have a const table of pointers to member functions
because the pointers to the functions would not change (constant
data). The quantity of pointers also doesn't change. Thus the
requirement for a constant table.

What I don't understand here is why not a static table.
Every reference has a name and a category. The category is used
to determine which table the data is stored in. For example, the
data for a "Book" reference would be placed into the book table,
and the data for a "Magazine" reference would be placed into the
magazine table. Instead of having one public "add_" method for
each category, I'm using one public method for the base class.

You say base class so presumably you are creating a singleton
for each category (Book, Magazine). Maybe the following will help

#include <iostream>
#include <ostream>

template < typename T >
struct Basic
{
// all "base class" code here
static int const array[];
static std::size_t const array_size;

int lookup( std::size_t i )
{
// possibly do something "non-static" here ...
return array[ i % array_size ];
}
};
template < typename T > std::size_t const Basic< T >::array_size =
sizeof( Basic< T >::array ) / sizeof( int )
;


// just change (define) the tables for each specialization
struct BookTag {};

template <> int const Basic< BookTag >::array[] = { 1, 2, 3 };

struct MagazineTag {};

template <> int const Basic< MagazineTag >::array[] = { 4, 5, 6, 7 };

int main()
{
using namespace std;

Basic< BookTag > bb;
cerr << "Book size: " << bb.array_size << endl;
cerr << "Book lookup 1: " << bb.lookup( 1 ) << endl;

Basic< MagazineTag > bm;
cerr << "Magazine size: " << bm.array_size << endl;
cerr << "Magazine lookup 1: " << bm.lookup( 1 ) << endl;

}



Rob.
 

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

Staff online

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top