C++ : Pointer to "new Class()" function - c++

I have a Parent abstract class, and derivated Foo and Bar classes. They all have a constructor taking a string name parameter. They have a string type() member function which returns "foo" and "bar" respectively.
Now I would like to build a dictionnary with keys "foo" and "bar", and values equal to pointers to functions creating a new instance of the corresponding class. This means these pointers will be of type Parent* (*) (const string &) and executing them will be equivalent to calling new Foo(name) and new Bar(name)
Can I avoid creating a static function for each class that will just call new, and get a pointer to this static function?
Thanks!
Edit : Actually, the goal behind this is implementing a plugin system in my app, the plugins adding new Derived class types. The plugin authors are generally my customers, and for this reason, I want to let them the most simple and elegant interface possible. So declaring and registering the factory functions should be as simple and as short as possible for them

Can I avoid creating a static function for each class that will just call new, and get a pointer to this static function?
Yes, you can create a generic function:
template <typename T>
ptr_type<Parent> create() {
return new T();
}
… and then take its address (but you need to get an address per derived type).
Note that I have explicitly not used T* as a return type – raw pointers should never own memory … an appropriate smart pointer should instead be used here.

What you describe is a factory method pattern.
Here's a link: http://en.wikipedia.org/wiki/Factory_method_pattern
The static function or a factory of some sort basically the thing you want.
Why do you want to avoid the static creation method?

You need to instantiate a factory function for each class you want to be able to build by this means. The following code shows you how to do so without having to recur to static members and by not writing by hand a number of different functions:
#include <iostream>
#include <map>
#include <functional>
#include <string>
#include <memory>
struct Parent{
Parent(std::string){}
};
struct Child1 : public Parent{
Child1(std::string d) : Parent(d){
std::cout << "Child1 constructor: " << d << std::endl;
}
};
struct Child2 : public Parent{
Child2(std::string d) : Parent(d){
std::cout << "Child2 constructor: " << d << std::endl;
}
};
template <typename Product, typename Return, typename Parameter>
Return factory(const Parameter& a){
return Return(new Product(a));
}
std::map<std::string, std::function<Parent*(std::string)> > mrp;
std::map<std::string, std::function<std::shared_ptr<Parent>(std::string)> > msp;
int main(){
mrp["Child1"] = &factory<Child1, Parent*, std::string>;
mrp["Child2"] = &factory<Child2, Parent*, std::string>;
Parent* a = mrp["Child1"]("one");
delete a;
std::unique_ptr<Parent> b(mrp["Child2"]("two"));
msp["Child1"] = &factory<Child1, std::shared_ptr<Parent>, std::string>;
msp["Child2"] = &factory<Child2, std::shared_ptr<Parent>, std::string>;
msp["Child1"]("one");
msp["Child2"]("two");
}
try this code here.
Also, as you can see, this method can be "configured" to use std::shared_ptr, raw pointers, ... and with different ownership semanthics, notice the line:
std::unique_ptr<Parent> b(mrp["Child2"]("two"));
However, any variation of what you briefly described in the question is, well, a variation of it! What you are trying to do is an abstract factory, which "standard" implementation relies exactly on making a factory function for each class you want to build. As I said, it doesn't need to be a static member of the class, it can well be a non-member non-friend function but this doesn't change very much (except better encapsulation, and the need for the constructor being public, or for the factory to be friend, which, somehow, breaks encapsulation).
The object factory is implemented in a very elegant way in loki. Refer to Modern C++ (Alexandrescu) for a thorough discussion of the design pattern itself as well as of the implementation given by loki.
As for your edit: registration in loki is sweet and simple as in (cited from the book):
// Implementation module for class Line
// Create an anonymous namespace
// to make the function invisible from other modules
namespace
{
Shape* CreateLine()
{
return new Line;
}
// The ID of class Line
const int LINE = 1;
// Assume TheShapeFactory is a singleton factory
// (see Chapter 6)
const bool registered =
TheShapeFactory::Instance().RegisterShape(
LINE, CreateLine);
}

Related

How to deal with constructors of differing length with the Factory design pattern?

I want to have a class that creates different sorts of objects based on a string I pass it. From my research, this best describes the Factory design pattern. I am having success implementing it, but I've run into a design issue: I don't know how to create objects with different length constructors.
Let's take for example, an abstract parent class called Pet. From it are 3 children: Fish, Cat, and Dog. They all inherit weight and color from Pet, so that goes in their constructors. But a fish might want a number of fins and a boolean regarding whether it is a saltwater fish. That's a 4 parameter constructor. Cat would like number of legs. That's 3 parameters. The dog might have parameters for legs, breed, and whether he plays well with other dogs, for 5 parameters.
In C++, I understand that there isn't any reflection, so the most common practice seems to be to just declare a map of string to function pointers, where the function pointer points to a function that looks something like this:
template<typename T> Pet* createObject(int weight, std::string color) {return new T(weight, color);}
Again, I'm not sure how I would stuff more parameters into the call without affecting the calls of other objects' constructors.
I can think of two workarounds: make new functions to accept different amount of parameters or make default parameters for constructors above a certain size.
Workaround 1 seems kind of excessive depending on how many different parameter sizes I have.
Workaround 2 seems to disregard the entire point of a constructor, as I will be forced to assign data after calling the constructor.
Are there any other better workarounds?
You can use variadic templates and perfect forwarding.
template<typename T, typename... Args>
Pet* createObject(Args&&... args) {
return new T(std::forward<Args>(args)...);
}
However, since any pointer can be converted to its base class, it would probably be better if this function returns T*. Moreover, using naked pointers is not wise, as you'll have to delete them manually. It's better to use shared_ptr or unique_ptr. For these classes there already are similar factory methods: make_shared and make_unique (the latter only in C++14). Or, if your compiler doesn't support C++11, then you can use shared_ptr and make_shared from Boost.
Of course this solution works when you know at compile time what type you'll need to create. If you have to decide it at runtime, then the whole problem has to be considered from a different direction, as if you don't know what type you are going to create, then there is no way you can know what parameters to give them, except for parameters common for all types. In this case what you need is an abstract factory pattern. Fortunately, C++ (at least from C++11) provides a way to implement this pattern without creating a hell lot of classes. For example, let's say you have to create instances of some class derived from Pet. The actual kind of pet, its size and other attributes are decided somewhere else, while the name of the pet is decided at the time of creation. Then, you'll need a factory like this:
typedef std::function<std::shared_ptr<Pet>(const std::string& name)> PetFactory;
At some point you decide that you want to create a Dog (I leave the meaning of the actual creation parameters to your imagination).
PetFactory petFactory =
[](const std::string& name) {
return std::make_shared<Dog>(name, 12, "brown", 23.5);
}
When you actually create it, all you need is to call the factory:
std::shared_ptr<Pet> pet = petFactory("Pet Name");
Is this what you need (forgive memory leaks and the like)
#include <map>
#include <string>
// definition of pet hierarcy
class pet_t
{
public:
virtual ~pet_t(void) {}
};
class frog_t : public pet_t
{
public:
frog_t(int) {}
static frog_t *builder(int n) { return new frog_t(n); }
};
class dog_t : public pet_t
{
public:
dog_t(const char *, int) {}
static dog_t *builder(const char *n, int p) { return new dog_t(n, p); }
};
// the per builder function type
typedef pet_t *(*pet_builder_t)(...);
// the map containing per builders: it's indexed by per type name
std::map<std::string, pet_builder_t> registry;
void build_factory(void)
{
registry["frog"] = reinterpret_cast<pet_builder_t>(&frog_t::builder);
registry["dog"] = reinterpret_cast<pet_builder_t>(&dog_t::builder);
}
// the actual factory function
template <class ...Ts>
pet_t *factory(std::string name, Ts&&...ts)
{
pet_builder_t builder = registry[name];
// assume there is something in the map
return builder(std::forward<Ts>(ts)...);
}
int main(int argc, char *argv[])
{
build_factory();
dog_t *dog = dynamic_cast<dog_t *>(factory(std::string("dog"), std::string("pluto"), 3));
frog_t *frog = dynamic_cast<frog_t *>(factory(std::string("frog"), 7));
}
I feel like there are too many casts but the idea should be a good starting point.
If when you create an object, you already know its parameters, and that it will be a Fish, you don't need a factory at all: just construct a Fish and you are done.
You can reasonably make use of a factory in case you don't know which object will result out of it, from the caller. For example you give as input of the factory method a string, maybe read from a file: the factory creates and returns the proper object type by parsing the string.
The caller don't know whether it will be a Fish or a Dog: that's the aim of the factory method.
And moreover you make use of a factory when you can extend it by adding more "constructable" objects by inheritance and overriding the virtual creationist method. That doesn't happen in case the methods have different signatures - they are in fact different methods
Well that was fun ! I've resorted to using factory sub-functions which parse the stream for arguments themselves. I've added in a Registrar pattern for simplicity of use, and of course a good dose of TMP.
Here is the abridged code :
/* Pet and derived classes omitted */
/* Registrar pattern omitted */
struct PetFactory {
using PetCtr = std::unique_ptr<Pet> (*)(std::istream &);
static auto make(std::istream &stream) {
std::string str;
stream >> str;
return ctrMap().at(str)(stream);
}
using PetCtrMap = std::map<std::string, PetCtr>;
static PetCtrMap &ctrMap();
};
template <class T, class... Args, std::size_t... Idx>
auto streamCtr_(std::istream &stream, std::index_sequence<Idx...> const &) {
std::tuple<Args...> args;
using unpack = int[];
unpack{0, (void(stream >> std::get<Idx>(args)), 0)...};
return std::make_unique<T>(std::move(std::get<Idx>(args))...);
}
template <class T, class... Args>
auto streamCtr(std::istream &stream) {
return std::unique_ptr<Pet>(streamCtr_<T, Args...>(
stream,
std::index_sequence_for<Args...>{}
));
}
int main() {
PetFactory::make("fish 1 silver 5 true");
PetFactory::make("cat 4 tabby 9");
PetFactory::make("dog 17 white husky playful");
}
Output:
I'm a 1kg silver fish with 5 fins, living in salty water.
I'm a 4kg tabby cat with 9 lives.
I'm a 17kg white husky and I'm playful.
The full commented code is available here on Coliru. Thanks for the challenge !
There are many approaches to this problem; the one I prefer may not be the most elegant, but it is extremely explicit. Basically, you create a map to boost::any pointers, and all constructors now simply take such a map.
using MyArgs = unordered_map<string, boost::any>;
class Fish {
Fish(MyArgs args) {
int num_fins = boost::any_cast<int>(args.at("num_fins"));
}
Now all of your constructors have the same signature, so your factory can just look this like:
unique_ptr<Pet> factory(string animal_name, MyArgs args) {
auto func = factory_map.at(animal_name);
return func(args);
}
Edit: I should also note that if you make a mistake, that is your MyArgs is missing an argument or has one of the wrong type, an exception will be thrown. So you can get a nice clear error and even handle it, as opposed to getting UB.

C++ One std::vector containing template class of multiple types

I need to store multiple types of a template class in a single vector.
Eg, for:
template <typename T>
class templateClass{
bool someFunction();
};
I need one vector that will store all of:
templateClass<int> t1;
templateClass<char> t2;
templateClass<std::string> t3;
etc
As far as I know this is not possible, if it is could someone say how?
If it isn't possible could someone explain how to make the following work?
As a work around I tried to use a base, non template class and inherit the template class from it.
class templateInterface{
virtual bool someFunction() = 0;
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction();
};
I then created a vector to store the base "templateInterface" class:
std::vector<templateInterface> v;
templateClass<int> t;
v.push_back(t);
This produced the following error:
error: cannot allocate an object of abstract type 'templateInterface'
note: because the following virtual functions are pure within 'templateInterface'
note: virtual bool templateInterface::someFunction()
To fix this error I made the function in templateInterface not a pure virtual by providing a function body, this compiled but when calling the function the overide is not used, but instead the body in the virtual function.
Eg:
class templateInterface{
virtual bool someFunction() {return true;}
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction() {return false;}
};
std::vector<templateInterface> v;
templateClass<int> i;
v.push_back(i);
v[0].someFunction(); //This returns true, and does not use the code in the 'templateClass' function body
Is there any way to fix this so that the overridden function is used, or is there another workaround to store multiple template types in a single vector?
Why your code doesn't work:
Calling a virtual function on a value doesn't use polymorphism. It calls the function which is defined for the type of this exact symbol as seen by the compiler, not the runtime type. When you insert sub types into a vector of the base type, your values will be converted into the base type ("type slicing"), which is not what you want. Calling functions on them will now call the function as defined for the base type, since not it is of that type.
How to fix this?
The same problem can be reproduced with this code snippet:
templateInterface x = templateClass<int>(); // Type slicing takes place!
x.someFunction(); // -> templateInterface::someFunction() is called!
Polymorphism only works on a pointer or reference type. It will then use the runtime type of the object behind the pointer / reference to decide which implementation to call (by using it's vtable).
Converting pointers is totally "safe" with regard to type slicing. Your actual values won't be converted at all and polymorphism will work as expected.
Example, analogous to the code snippet above:
templateInterface *x = new templateClass<int>(); // No type slicing takes place
x->someFunction(); // -> templateClass<int>::someFunction() is called!
delete x; // Don't forget to destroy your objects.
What about vectors?
So you have to adopt these changes in your code. You can simply store pointers to actual types in the vector, instead of storing the values directly.
When working with pointers you also have to care about deleting your allocated objects. For this you can use smart pointers which care about deletion automatically. unique_ptr is one such smart pointer type. It deletes the pointee whenever it goes out of scope ("unique ownership" - the scope being the owner). Assuming the lifetime of your objects is bound to the scope this is what you should use:
std::vector<std::unique_ptr<templateInterface>> v;
templateClass<int> *i = new templateClass<int>(); // create new object
v.push_back(std::unique_ptr<templateInterface>(i)); // put it in the vector
v.emplace_back(new templateClass<int>()); // "direct" alternative
Then, call a virtual function on one of these elements with the following syntax:
v[0]->someFunction();
Make sure you make all functions virtual which should be possible to be overridden by subclasses. Otherwise their overridden version will not be called. But since you already introduced an "interface", I'm sure you are working with abstract functions.
Alternative approaches:
Alternative ways to do what you want is to use a variant type in the vector. There are some implementations of variant types, the Boost.Variant being a very popular one. This approach is especially nice if you don't have a type hierarchy (for example when you store primitive types). You would then use a vector type like std::vector<boost::variant<int, char, bool>>
Polymorphism only works through pointers or references. You'll
need the non-template base. Beyond that, you'll need to decide
where the actual objects in container will live. If they're all
static objects (with sufficient lifetime), just using
a std::vector<TemplateInterface*>, and inserting with
v.push_back(&t1);, etc., should do the trick. Otherwise,
you'll probably want to support cloning, and keep clones in the
vector: preferably with Boost pointer containers, but
std::shared_ptr can be used as well.
The solutions given so far are fine though be aware that in case you were returning the template type other than bool in your example , none of these would help as the vtable slots would not be able to be measured before hand. There are actually limits , from a design point of view , for using a template oriented polymorphic solution.
Solution nr. 1
This solution inspired by Sean Parent's C++ Seasoning talk. I highly recommend to check it out on youtube. My solution simplified a bit and the key is to store object in method itself.
One method only
Create a class that will invoke method of stored object.
struct object {
template <class T>
object(T t)
: someFunction([t = std::move(t)]() { return t.someFunction(); })
{ }
std::function<bool()> someFunction;
};
Then use it like this
std::vector<object> v;
// Add classes that has 'bool someFunction()' method
v.emplace_back(someClass());
v.emplace_back(someOtherClass());
// Test our vector
for (auto& x : v)
std::cout << x.someFunction() << std::endl;
Several methods
For several methods use shared pointer to share object between methods
struct object {
template <class T>
object(T&& t) {
auto ptr = std::make_shared<std::remove_reference_t<T>>(std::forward<T>(t));
someFunction = [ptr]() { return ptr->someFunction(); };
someOtherFunction = [ptr](int x) { ptr->someOtherFunction(x); };
}
std::function<bool()> someFunction;
std::function<void(int)> someOtherFunction;
};
Other types
Primitive types (such as int, float, const char*) or classes (std::string etc.) may be wrapped in the same way as object class do but behave differently. For example:
struct otherType {
template <class T>
otherType(T t)
: someFunction([t = std::move(t)]() {
// Return something different
return true;
})
{ }
std::function<bool()> someFunction;
};
So now it is possible to add types that does not have someFunction method.
v.emplace_back(otherType(17)); // Adding an int
v.emplace_back(otherType("test")); // A string
Solution nr. 2
After some thoughts what we basically done in first solution is created array of callable functions. So why not just do the following instead.
// Example class with method we want to put in array
struct myclass {
void draw() const {
std::cout << "myclass" << std::endl;
}
};
// All other type's behaviour
template <class T>
void draw(const T& x) {
std::cout << typeid(T).name() << ": " << x << std::endl;
}
int main()
{
myclass x;
int y = 17;
std::vector<std::function<void()>> v;
v.emplace_back(std::bind(&myclass::draw, &x));
v.emplace_back(std::bind(draw<int>, y));
for (auto& fn : v)
fn();
}
Conclusion
Solution nr. 1 is definitely an interesting method that does not require inheritance nor virtual functions. And can be used to other stuff where you need to store a template argument to be used later.
Solution nr. 2, on the other hand, is simpler, more flexible and probably a better choice here.
If you're looking at a container to store multiple types, then you should explore boost variant from the popular boost library.

How can I instantiate an object knowing only its name? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is there a way to instantiate objects from a string holding their class name?
In C++, I want to have my user enter the object type name to be created at run-time, and, depending on the string I get from them, the program will instantiate the correct object (in short, I'm implementing factory method pattern). However, if the program has to support a new object type, then modifying existing code is not allowed.
So is it possible to remove all the if...else if...else if... stuff from the method, and still have my program instantiate a correct object of a specific product type (out of many, which are known only at compile time)?
My searching around got me this link: Is there a way to instantiate objects from a string holding their class name? and it seems it's what I want but I can't understand the code at all.
Any help would be really appreciated.
This will only work if all the required classes are derived from some common base class, and you will generally be limited to using the base interface (though you can work around that with some additional effort). Here's one approach:
// Immutable core code:
#include <map>
#include <string>
class Base
{
typedef Base * (*crfnptr)(const std::string &);
typedef std::map<std::string, crfnptr> CreatorMap;
static CreatorMap creators;
public:
virtual ~Base() { }
Base * clone() const { return new Base(*this); }
static Base * create_from_string(std::string name)
{
CreatorMap::const_iterator it = creators.find(name);
return it == creators.end() ? NULL : it->first();
}
static void register(std::string name, crfnptr f)
{
creators[name] = f;
}
};
Now you can add new derived classes from your new code:
// your code:
#include "immutable_core.hpp"
class Foo : public Base
{
public:
Foo * clone() const { return new Foo(*this); }
static Foo * create() { return new Foo; }
};
Base::register("Foo", &Foo::create);
To create a class, you simply call Base * p = Base::create_from_string("Foo");.
You can do that implementing something like a plugin system. I've implemented this in Linux with dlopen. The program doesn't need to be modified, but you need only add new classes as dynamic libraries that will be loaded at runtime.
You can start here for more info: C++ dlopen mini HOWTO

Create object based on class name provided in text file?

I'm wondering, is it possible in C++ to use a text value read in from a file to create an object of a class of that name eg.
contents of file: "MyClass"
code: read file
code: instantiate "MyClass" object.
I'd like to avoid a whole series of hardcoded if/then/elses if possible.
Sorry I'm not sure how to describe this problem in more technical terms!
As long as you don't mind some restrictions, this is fairly easy to do. The easiest way to do the job restricts you to classes that descend from one common base class. In this case, you can do something like this:
// warning: I've done this before, but none of this code is tested. The idea
// of the code works, but this probably has at least a few typos and such.
struct functor_base {
virtual bool operator()() = 0;
};
You'll then obviously need some concrete classes derived from that base:
struct eval_x : functor_base {
virtual bool operator()() { std::cout << "eval_x"; }
};
struct eval_y : functor_base {
virtual bool operator()() { std::cout << "eval_y"; }
};
Then we need some way to create an object of each type:
functor_base *create_eval_x() { return new eval_x; }
functor_base *create_eval_y() { return new eval_y; }
Finally, we need a map from the names to the factory functions:
// the second template parameter is:
// pointer to function returning `functor_base *` and taking no parameters.
std::map<std::string, functor_base *(*)()> name_mapper;
name_mapper["eval_x"] = create_eval_x;
name_mapper["eval_y"] = create_eval_y;
That (finally!) gives us enough so we can map from a name to a function object:
char *name = "eval_x";
// the map holds pointers to functions, so we need to invoke what it returns
// to get a pointer to a functor:
functor_base *b = name_mapper.find(name)();
// now we can execute the functor:
(*b)();
// since the object was created dynamically, we need to delete it when we're done:
delete b;
There are, of course, many variations on the general theme. For example, instead of factory functions that create objects dynamically, you can create an instance of each object statically, and just put the address of the static object in the map.
you can use abstract factory to do this. Limitations are the classes need to implement a base class and you need to register the factory class with the abstract factory.
class AbstractFactory;
class Factory;
class Object;
// base marker class for all the classes that need this instantiation strategy
class Object{}
class Factory
{
public:
//override this in concrete factories
virtual Object* create() = 0;
};
// helper macro to declare an inner class that's a default factory
#define DECL_DEFAULT_FACTORY(ObjectClass) class Factory : public Factory \
{\
public:\
Factory(){}\
virtual ~Factory(){}\
Object* create(){ return new ObjectClass(); } \
}
// this can be made a singleton
class AbstractFactory
{
public:
void registerClass(const String& clsName, Factory* factory){ //put this in a std::map }
void deregisterClass(const String& className){ //remove factory from map and delete the ptr }
Object* create(const String& className)
{
Factory* factory = factories[className];
if(factory){ return factory->create(); }
else{ return 0; }
}
};
so it shall be used like:
class SampleClass : public Object
{
//impl goes here
DECL_DEFAULT_FACTORY(SampleClass);
}
and somewhere else you need to do
abstractFactoryInstance->registerClass("SampleClass",new SampleClass::Factory());
then your AbstractFactory is ready to do
SampleClass* obj = (SampleClass*)(abstractFactoryInstance->create("SampleClass"));
you can further refine the scheme by declaring template classes for Factory
Most C++ frameworks (e.g., MFC, Boost) support some kind of object serialization, though it doesn't generally take the form of a human-readable text file. In C++, all of the class types whose instances are recorded in a file have to be present (i.e., compiled and linked into) a program in order for that program to either write or read (and create objects from) such a file.
With Compiled languages like C++, you won't be able to do so.
Such things are only possible with interpreted languages, such as PHP.
What you need is boost serializarion. This will allow you to persist your objects in a file. You can find an example here.

Storing values of any type as type initially supplied in templated factory method in C++?

This is a slightly different question to this one ([Accessing a method from a templated derived class without using virtual functions in c++?) which I asked recently.
I would like to create an instance of an object using a templated factory method, then from then on only be able to set and get a value based on the initial type supplied to the item.
Here's a quick example of what I'm trying to achieve:
boost::shared_ptr<Item> item = Item::create<float>();
item->setValue(5); // conversion to 5.0 in setting the value
float value = item->value(); // returned value = 5.0
Essentially the only time setValue will fail is if there isn't an implicit conversion from whatever has been supplied to the initial 'type' of the internal value in Item.
So if I made the whole Item class a templated class taking a type, I would need to provide the type of the value every time I created a shared pointer to the Item, which I don't really care about.
The next approach I took was to try and store the initial type in the class and use boost::any for the internal storage, casting the internal type to the initial type specified if there was an implicit conversion. However, I stuggled to store and compare the type information, initially looking at std::type_info, but as setValue took a boost::any, had no way of comparing what was actually passed.
(A slight extension to this might be providing a variant-style list of options to the template argument in the creation and returning the value in the native supplied type.)
There may be a design pattern I'm not aware of, or a different approach I haven't considered, so I'd be interested in hearing any suggestions of how to tackle this?
Consider this:
boost::shared_ptr<Item> item1 = Item::create<float>();
boost::shared_ptr<Item> item2 = Item::create<string>();
item1 and item2 have the same (static) type: boost::shared_ptr. So there isn't any way you can make this compile:
item2.setValue("foo");
and have this fail to compile:
item1.setValue("foo");
I'm not sure what you're saying about "if I made the whole Item class a templated class taking a type, I would need to define this every time I call setValue or value (setValue<float>(5))". It sounds like you're actually talking about making each method templated, not the whole class. If the Item class was templated then you'd write:
boost::shared_ptr<Item<float> > item = Item<float>::create();
and then you can easily have the setValue() method accept only the matching type.
Does this work for you?
#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;
using namespace boost;
template<typename T> class Item
{
Item(); // prohibited
Item (const T & t) : m_value(t) {}
public :
static shared_ptr<Item<T>> Create(const T & t)
{ return shared_ptr<Item<T>>(new Item<T>(t)); }
const T & getValue() const { return m_value; }
void setValue(const T & v) { m_value = v; }
private :
T m_value;
};
template<typename T> class Factory
{
public :
static shared_ptr<Item<T>> CreateItem(const T & value)
{ return Item<T>::Create(value); }
};
void main()
{
shared_ptr<Item<int>> a = Factory<int>::CreateItem(5);
shared_ptr<Item<float>> b = Factory<float>::CreateItem(6.2f);
std::cout << a->getValue() << std::endl;
std::cout << b->getValue() << std::endl;
a->setValue(3);
b->setValue(10.7f);
std::cout << a->getValue() << std::endl;
std::cout << b->getValue() << std::endl;
}
edit - enforced more const-ness nazism.
Your problem with boost::any is that it's too flexible. The basic idea behind it is still sane. What you need to do is wrap the initial value in an object of type template<typename T> class ItemOfType<T> : public Item. Item::create<T> would then return such a typed object. When you later try to assign a U, you first test if you can dynamic_cast your this to ItemOfType<U>*. This covers your T==U case.
The harder part is the question whether a U is assignable to a T. The usual solution is to instantiate templates, but in your create<T> you don't have the U and in your Item::operator=(U const) you don't have the original T.
This sounds very similar to boost.any. Have you look at this already?