I have implemented a pure C++11 Any class (based on this code) which is similar to boost::any and works nicely if used directly.
However I need to use this now as template parameter to assign parameters to variables. Look at this:
class A {
IRecognizer<Any, Any> *_recognizer;
template <typename T1, typename T2>
A(IRecognizer<T1, T2> *x) : _recognizer(x) {
}
}
and
template<typename Symbol, typename ATNInterpreter>
class IRecognizer {
public:
virtual int getState() = 0;
};
Even though I could assign each template parameter to an Any variable, I'm not allowed to assign IRecognizer<T1, T2> to IRecognizer<Any, Any>. Is there a solution for this problem? The error message is:
Cannot initialize a member subobject of type 'IRecognizer<Any, Any> *'
with an lvalue of type 'IRecognizer<Token *, ParserATNSimulator *> *'
The reason I use the Any class is to have a common type that could be assigned with any class reference (similar to Java's Object, but C++ has no common object type from which all other classes derive).
Maybe a different approach is possible here? I'm open for suggestions.
You are trying to convert a IRecognizer<T1, T2> * to a IRecognizer<Any, Any> *. The only allowed pointer conversion is from a derived class pointer to a base class pointer (i.e. Derived* to Base*) or to a more cv-qualified pointer to the same type (i.e. Derived* to Derived const*) or both.
IRecognizer<T1,T2> is not in the same class hierarchy as IRecognizer<Any, Any>. They are two unrelated types. You can add a constructor to convert an IRecognizer<A,B> to an IRecognizer<C,D> if that makes sense, but you can't add a similar thing for pointers.
A pointer to X is not the same as an X.
While you can convert an X into a Y (a IRecognizer<T1,T2> into an IRecognizer<Any,Any>), you cannot convert a pointer to X into a pointer to Y.
You may not want a pointer here. Instead, you might want a value.
However, an interface is not a value.
Java generics are not like C++ templates. A Java generic Bob<Type> is a wrapper around Bob<Object> -- it is actually storing an Object, with a bunch of wrapping casts to-and-from in a layer on top of it.
You can write such wrappers in C++. As an example:
class IRecognizer_base {
public:
virtual int getState() = 0;
};
template<typename Symbol, typename ATNInterpreter>
class IRecognizer:public IRecognizer_base {
};
Now, suppose getState() returned a Symbol:
class IRecognizer_base {
public:
virtual Any getState_() = 0;
};
template<typename Symbol, typename ATNInterpreter>
class IRecognizer:public IRecognizer_base {
public:
inline Symbol getState() {
return getState_(); // whatever conversion required to go from `Any` to `Symbol`
}
};
here, we expose the fact that our objects actually return an Any, but in the interface we cast them over.
If you actually exposed what operations are actually different based on the template types, you can do type erasing tactics that let you store anything that can do those operations instead of a pointer to a specific type.
Related
I am trying to write a class that I can store and use type information in without the need for a template parameter.
I want to write something like this:
class Example
{
public:
template<typename T>
Example(T* ptr)
: ptr(ptr)
{
// typedef T EnclosedType; I want this be a avaialable at the class level.
}
void operator()()
{
if(ptr == NULL)
return;
(*(EnclosedType*)ptr)(); // so i can cast the pointer and call the () operator if the class has one.
}
private:
void* ptr;
}
I am not asking how to write an is_functor() class.
I want to know how to get type information in a constructor and store it at the class level. If that is impossible, a different solution to this would be appreciated.
I consider this as a good and valid question, however, there is no general solution beside using a template parameter at the class level. What you tried to achieve in your question -- using a typedef inside a function and then access this in the whole class -- is not possible.
Type erasure
Only if you impose certain restrictions onto your constructor parameters, there are some alternatives. In this respect, here is an example of type erasure where the operator() of some given object is stored inside a std::function<void()> variable.
struct A
{
template<typename T>
A(T const& t) : f (std::bind(&T::operator(), t)) {}
void operator()() const
{
f();
}
std::function<void()> f;
};
struct B
{
void operator()() const
{
std::cout<<"hello"<<std::endl;
}
};
int main()
{
A(B{}).operator()(); //prints "hello"
}
DEMO
Note, however, the assumptions underlying this approach: one assumes that all passed objects have an operator of a given signature (here void operator()) which is stored inside a std::function<void()> (with respect to storing the member-function, see here).
Inheritance
In a sense, type erasure is thus like "inheriting without a base class" -- one could instead use a common base class for all constructor parameter classes with a virtual bracket operator, and then pass a base class pointer to your constructor.
struct A_parameter_base
{
void operator()() const = 0;
};
struct B : public A_parameter_base
{
void operator()() const { std::cout<<"hello"<<std::endl; }
};
struct A
{
A(std::shared_ptr<A_parameter_base> _p) : p(_p) {}
void operator()()
{
p->operator();
}
std::shared_ptr<A_parameter_base> p;
}
That is similar to the code in your question, only that it does not use a void-pointer but a pointer to a specific base class.
Both approaches, type erasure and inheritance, are similar in their applications, but type erasure might be more convenient as one gets rid of a common base class. However, the inheritance approach has the further advantage that you can restore the original object via multiple dispatch
This also shows the limitations of both approaches. If your operator would not be void but instead would return some unknown varying type, you cannot use the above approach but have to use templates. The inheritance parallel is: you cannot have a virtual function template.
The practical answer is to store either a copy of your class, or a std::ref wrapped pseudo-reference to your class, in a std::function<void()>.
std::function type erases things it stores down to 3 concepts: copy, destroy and invoke with a fixed signature. (also, cast-back-to-original-type and typeid, more obscurely)
What it does is it remembers, at construction, how to do these operations to the passed in type, and stores a copy in a way it can perform those operations on it, then forgets everything else about the type.
You cannot remember everything about a type this way. But almost any operation with a fixed signature, or which can be intermediaried via a fixed signature operation, can be type erased down to.
The first typical way to do this are to create a private pure interface with those operations, then create a template implementation (templated on the type passed to the ctor) that implements each operation for that particular type. The class that does the type erasure then stores a (smart) pointer to the private interface, and forwards its public operations to it.
A second typical way is to store a void*, or a buffer of char, and a set of pointers to functions that implement the operations. The pointers to functions can be either stored locally in the type erasing class, or stored in a helper struct that is created statically for each type erased, and a pointer to the helper struct is stored in the type erasing class. The first way to store the function pointers is like C-style object properties: the second is like a manual vtable.
In any case, the function pointers usually take one (or more) void* and know how to cast them back to the right type. They are created in the ctor that knows the type, either as instances of a template function, or as local stateless lambdas, or the same indirectly.
You could even do a hybrid of the two: static pimpl instance pointers taking a void* or whatever.
Often using std::function is enough, manually writing type erasure is hard to get right compared to using std::function.
Another version to the first two answers we have here - that's closer to your current code:
class A{
public:
virtual void operator()=0;
};
template<class T>
class B: public A{
public:
B(T*t):ptr(t){}
virtual void operator(){(*ptr)();}
T*ptr;
};
class Example
{
public:
template<typename T>
Example(T* ptr)
: a(new B<T>(ptr))
{
// typedef T EnclosedType; I want this be a avaialable at the class level.
}
void operator()()
{
if(!a)
return;
(*a)();
}
private:
std::unique_ptr<A> a;
}
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.
I have a base class, Parameter, and two derived classes: Scalar & Vector. In each derived class, I have a member function which takes a function pointer as input:
In the Scalar class:
typedef double (*samplerType)(RandNum& rnState);
void RegisterSampler( samplerType input );
In the Vector class:
typedef std::vector<double> (*samplerType)(RandNum& rnState);
void RegisterSampler( samplerType input );
Note the different return types: double and std::vector<double>. I would like to define this function within the mutual base class, Parameter -- so I changed the functions to take (void* input) and then tried the following when defining the functions within the Scalar & Vector classes:
samplerType inputSampler = dynamic_cast< samplerType >(input);
However, I get the following error in VS 2005:
error C2680: 'double (__cdecl *)(RandNum &)' : invalid target type for dynamic_cast
target type must be a pointer or reference to a defined class
Grumble Grumble Grumble... I'm not sure if this is valid (standard permitting) C++ or not, but I guess either way I'll treat this as a flaw in my design.
So, My standard approach would be to template the base class with the return type of the function, but I can't. The base class, Parameter, must -- by design -- be free of all type information. Is there a different way to design the inheritance?
My attempts to Google this have turned up virtually nil on function pointers -- Hence I'll believe that this is in fact invalid syntax, but perhaps just a really, really uncommon design challenge? Is this another one of those places, functors to the rescue?
Aside from the design flaw that James points out, it's true that you can't cast from a function pointer to a normal void* pointer. You can however cast between function pointers of arbitary types (free-to-free, member-to-member):
typedef void (*samplerType)();
// in base class ...
samplerType sampler_;
template<class F>
void RegisterSampler(F sampler){
// template so the user doesn't have to do the type cast
sampler_ = reinterpret_cast<samplerType>(sampler);
}
// in derived class, where you access the sampler, you need to cast it back:
// (scalar)
typedef double (*realSamplerType)(RandNum& rnState);
// made-up function ...
void UseSampler(){
realSamplerType sampler = reinterpret_cast<realSamplerType>(sampler_);
double ret = sampler(param...);
}
I was looking at the boost serialization library, and the intrusive way to provide support for serialization is to define a member function with signature (simplifying):
class ToBeSerialized {
public:
//Define this to support serialization
//Notice not virtual function!
template<class Archive>
void serialize(Archive & ar)
{.....}
};
Moreover, one way to support serilization of derived class trough base pointers is to use a macro of the type:
//No mention to the base class(es) from which Derived_class inherits
BOOST_CLASS_EXPORT_GUID(Derived_class, "derived_class")
where Derived_class is some class which is inheriting from a base class, say Base_class. Thanks to this macro, it is possible to serialize classes of type Derived_class through pointers to Base_class correctly.
The question is:
I am used in C++ to write abstract factories implemented through a map from std::string to (pointer to) functions which return objects of the desired type (and eveything is fine thanks to covariant types).
Hover I fail to see how I could use the above non-virtual serialize template member function to properly de-serialize (i.e. construct) an object without knowing its type (but assuming that the type information has been stored by the serializer, say in a string).
What I would like to do (keeping the same nomenclature as above) is something like the following:
XmlArchive xmlArchive; //A type or archive
xmlArchive.open("C:/ser.txt"); //Contains type information for the serialized class
Base_class* basePtr = Factory<Base_class>::create("derived_class",xmlArchive);
with the function on the righ-hand side creating an object on the heap of type Derived_class (via default constructor, this is the part I know how to solve) and calling the serialize function of xmlArchive (here I am stuck!), i.e. do something like:
Base_class* Factory<Base_class>::create("derived_class",xmlArchive)
{
Base_class* basePtr = new Base_class; //OK, doable, usual map string to pointer to function
static_cast<Derived_class*>( basePtr )->serialize( xmlArchive ); //De-serialization, how?????
return basePtr;
}
I am sure this can be done (boost serialize does it but its code is impenetrable! :P), but I fail to figure out how.
The key problem is that the serialize function is a template function. So I cannot have a pointer to a generic templated function.
As the point in writing the templated serialize function is to make the code generic (i.e. not having to re-write the serialize function for different Archivers), it does not make sense then to have to register all the derived classes for all possible archive types, like:
MY_CLASS_REGISTER(Derived_class, XmlArchive);
MY_CLASS_REGISTER(Derived_class, TxtArchive);
...
In fact in my code I relies on overloading to get the correct behaviour:
void serialize( XmlArchive& archive, Derived_class& derived );
void serialize( TxtArchive& archive, Derived_class& derived );
...
The key point to keep in mind is that the archive type is always known, i.e. I am never using runtime polymorphism for the archive class...(again I am using overloading on the archive type).
Any suggestion to help me out?
Thank you very much in advance!
Cheers
All you need is to store some sort of identifier before storing the information from the derived type. Then upon reading you use that identifier, which you've read first, to direct you to a factory that can then interpret the next block of information correctly and generate your derived type. This is probably what boost::serialization does at a very basic level. Maybe something like so:
ar >> type;
Base_class* basePtr = Factory<Base_class>::create(type,xmlArchive);
Then you have a map of objects that look something like so:
struct reader_base { virtual void load(xmlArchive, base_ptr) = 0; }
template < typename T >
struct reader : reader_base
{
virtual void load(xmlArchive, base_ptr)
{
static_cast<T*>(base_ptr)->serialize(xmlArchive);
}
};
If your archive type is always known, why bother parameterizing your serialize function on it? There's an argument to be made for code reuse, yes, but if your Archive class ever changes its definition or gets replaced, you will likely need to refactor some of your serialization code anyway.
If you stick with:
class ToBeSerialized : public Base_class {
public:
void serialize(Archive & ar)
{.....}
};
You can then take a pointer to your serialize function, and bind it to your factory.
You will also need to bind separate create functions for each class, so that it can instantiate the right type when it's asked for it. Something like:
template <typename T> Base_class* Factory::create(Archive& xmlArchive) {
T* derivedPtr = new T;
derivedPtr->serialize( xmlArchive );
return derivedPtr;
}
The factory will then need a generic create method that calls out to the correct static parameterized create<T>:
Base_class* Factory::create(const char* typeString, Archive& xmlArchive) {
// Pseudocode.
return m_map.find(typeString)->callCreate(xmlArchive);
}
Static array initialization... with const pointers... to overloaded, templatized member functions. Is there a way it can be done (C++03 standard code)? I mean, if I have the template class
template <class T1, class U1, typename R1>
class Some_class {
public:
typedef T1 T;
typedef U1 U;
typedef R1 R;
R operator()(T& v) { /* dereference pointer to a derived class (U),
overloaded member function (U::f) */ };
private:
static R (U::* const pmfi[/* # of overloaded functions in U */])(T&);
};
Used as
template <class BASE, typename RET>
class Other_class : public Some_class<BASE, Other_class<BASE, RET>, RET> {
RET f(/* type derived from BASE */) {}
RET f(/* other type derived from BASE */) {}
RET f(/* another type derived from BASE */) {}
...
};
Question: how can I initialize de array pmfi (no typedefs, please)?
Notes:
1. As a static array MUST be initialized at file scope, template parameters and pmfi must be full qualified (the only way I know to access template parameters outside a class scope is to typedef them...).
2. So far so good. No problems with the compiler (Comeau 4.3.10.1). Problems start popping up when I try to fullfill the initializer list { ... }.
2.1. The compiler complains the template argument list is missing, no matter what I do.
2.2. I have no idea how to select the correct overloaded U::f function.
BTW, this is a kind of "jump table" generator from a boost.preprocessor list. The code I am trying to implement is of course much more complex then this one, but this is his essence.
Thanks for any help
To use BOOST_PP_ENUM in the way that you've shown, you would need a macro that takes a 'number' and yields an expression that is the address of an appropriate member of the appropriate class. I don't see a good way to do this without an explicit list unless the desired functions all have manufactured names (e.g. memfun1, memfun2, etc.). Except in the case, it's going to be easier to list the function address expressions explicitly that to used BOOST_PP_ENUM.
You are using identifiers in this array that are the same as the template parameters in Some_class.
R (U::* const pmfi[])(T&) = { /* ... */ }
Is this really supposed to be the templated member of Some_class?
template< class T, class U, class R >
R (U::* const Some_class<T, U, R>::pmfi[])(T&) = { /* ... */ }
If so, is the same instantiation going to work with all combinations of types that you are going to us the template Some_class with? If so, you have a very constrained set of classes, perhaps you can do away with the template. If not, you are going to have to specialize Some_class for every combination of template parameters in which case the template is not gaining you very much.
Edit, post edit: If I've understood you correctly then you can't do what you've suggested because the array of pointers must be of exactly the right signature.
Reducing it to a simple function pointer example, you can't do this:
void f(Derived&);
void (*p)(Base&) = &f;
otherwise, it would subvert type safety:
OtherDerived od; // derived from Base, but no from Derived
// I've managed to pass something that isn't a Derived reference to f
// without an explicit (and dangerous) cast
(*p)(od);
In your array of function pointers, the initializers must all be to functions of the right signature.