Re: '*' cannot appear in a constant-expression problem
On 2008-10-24, Stefano Sabatini <stefano.sabatini@caos.org> wrote:
Hi all, I'm encountering this while trying to implement a factory
singleton method to generate objects.
The singleton has a static map which binds a static creation function
defined in each class to the type of the object to be created.
Here it is the code, which is a modification of the wikipedia C++
factory example code:
----------------------------------8<--------------------------------
[...]
----------------------------------8<--------------------------------
Sorry it had tons of erros, check below the new version.
The static map declaration syntax is somehow wrong, and after hitting
my head sometime I still can't get out of it.
I'm using g++ 4.3.1, and the syntax error I get is this:
make PizzaFactory2; and PizzaFactory2
g++ -I/home/stefano/opt/reilabs/include -I/home/stefano/include -O0 -g -ggdb PizzaFactory2.cxx -c -o PizzaFactory2.o
PizzaFactory2.cxx:50: error: `*' cannot appear in a constant-expression
PizzaFactory2.cxx:50: error: a function call cannot appear in a constant-expression
PizzaFactory2.cxx:50: error: `*' cannot appear in a constant-expression
PizzaFactory2.cxx:50: error: a function call cannot appear in a constant-expression
PizzaFactory2.cxx:50: error: a function call cannot appear in a constant-expression
PizzaFactory2.cxx:50: error: template argument 2 is invalid
The exact line of the error is:
static std::map<std::string, (Pizza *)(*)()> creators;
which I interpret as:
a static map from string to a static method pointer which takes no
parameters and returns a pointer to a Pizza object.
What am I missing or what I'm doing wrongly?
Well I found a solution, even if I'm not sure I really understood it.
If I define the type like this:
typedef Pizza *(* pizza_creator_fn_ptr)();
and then use the map like this:
static map<std::string, pizza_creator_fn_ptr> creators;
then it seems to work fine.
A short explanation would be nice.
New version here:
-----------------------------------8<-------------------------------------
#include <string>
#include <iostream>
#include <map>
class Pizza {
public:
virtual void get_price() = 0;
};
class HamAndMushroomPizza: public Pizza {
public:
virtual void get_price() {
std::cout << "Ham and Mushroom: $8.5" << std::endl;
}
static Pizza* create_pizza() {
return new HamAndMushroomPizza;
}
};
class DeluxePizza : public Pizza {
public:
virtual void get_price() {
std::cout << "Deluxe: $10.5" << std::endl;
}
static Pizza* create_pizza() {
return new DeluxePizza;
}
};
class SeafoodPizza : public Pizza {
public:
virtual void get_price() {
std::cout << "Seafood: $11.5" << std::endl;
}
static Pizza* create_pizza() {
return new SeafoodPizza;
}
};
typedef Pizza* (*pizza_creator_fn_ptr)(void);
class PizzaFactory {
private:
static std::map<std::string, pizza_creator_fn_ptr> creators;
void init() {
creators["Deluxe"] = &DeluxePizza::create_pizza;
creators["Ham and Mushroom"] = &HamAndMushroomPizza::create_pizza;
creators["Seafood"] = &SeafoodPizza::create_pizza;
}
public:
static PizzaFactory* get_instance()
{
static PizzaFactory * instance = 0;
if (!instance) {
instance = new PizzaFactory;
instance->init();
}
return instance;
}
static Pizza* create_pizza(const std::string& type) {
std::map<std::string, pizza_creator_fn_ptr>::iterator it;
if ((it = creators.find(type)) != creators.end())
return (*(it->second))();
else
return 0;
}
};
//usage
int main() {
PizzaFactory* factory = PizzaFactory::get_instance();
Pizza *pizza = 0;
pizza = factory->create_pizza("Default");
pizza->get_price();
delete pizza;
pizza = factory->create_pizza("Ham and Mushroom");
pizza->get_price();
delete pizza;
pizza = factory->create_pizza("Seafood Pizza");
pizza->get_price();
delete pizza;
}
-----------------------------------8<-------------------------------------
The code has still a problem related to the use of the static map
which isn't found by the compiler, but this is another problem.
Thanks for your attention.