If I have a polymorphic base class called Base as well as classes Derived1 and Derived2 which inherit from Base. I can then use boost::lambda to create a factory of sorts. Something like:
typedef boost::function<Base *()> Creator;
std::map<std::string,Creator> map1;
map1["Derived1"] = boost::lambda::new_ptr<Derived1>();
map1["Derived2"] = boost::lambda::new_ptr<Derived2>();
(This isn't real code, I'm just trying to illustrate the problem.)
This works, so I can then do a lookup in the map using a string and then invoke the lambda function to instantiate that class. All good.
The problem with this is that it's dealing in raw pointers, I'd prefer to be using smart pointers (std::shared_ptr).
So if I change from:
typedef boost::function<Base *>() Creator;
to:
typedef boost::function<std::shared_ptr<Base> >() Creator;
Then I'm getting stuck from here. I've tried using boost::lambda::bind in conjunction with boost::lambda::new_ptr but I'm not having much luck, can't get past compilation errors. (Huge reams of template-related error output.)
I've checked other similar messages within StackOverflow, Using boost::bind and boost::lambda::new_ptr to return a shared_ptr constructor is close but if I try to apply its solution I get the template errors mentioned above.
I'm happy to provide sample code and the actual errors if it helps, but hopefully the above info is sufficient. I'm using boost 1.47.0 on GCC 4.6 as well as 4.7 snapshot on Fedora 15.
class Base {
public:
virtual ~Base() = 0;
};
Base::~Base() {}
class Derived1 : public Base {};
class Derived2 : public Base {};
typedef boost::shared_ptr<Base> BasePtr;
typedef boost::function<BasePtr()> Creator;
template <typename T>
Creator MakeFactory()
{
namespace la = boost::lambda;
return la::bind(
la::constructor<BasePtr>(),
la::bind(la::new_ptr<T>()));
}
int _tmain(int argc, _TCHAR* argv[])
{
std::map<std::string,Creator> map1;
map1["Derived1"] = MakeFactory<Derived1>();
map1["Derived2"] = MakeFactory<Derived2>();
BasePtr p1 = map1["Derived1"]();
BasePtr p2 = map1["Derived2"]();
return 0;
}
however, why go to the trouble when you could write:
template <typename T>
BasePtr MakeFactoryImpl()
{
return BasePtr(new T());
}
template <typename T>
Creator MakeFactory()
{
return Creator(&MakeFactoryImpl<T>);
}
This is a common problem. The fact that two types are related (in your case by inheritance) does not imply that the instantiations of a template with those two types maintains the same relationship.
The solution is to return always shared_ptr<Base>, since it can hold both pointers to Base or any derived type, which will be semantically compatible with your current version (i.e. in both versions the caller gets a (smart)-pointer-to Base.
As an aside, I would avoid returning shared_ptr from a factory, as you are forcing your choice of smart pointer into all of your users. I would prefer to either return a raw pointer (the user can choose, but it is dangerous in some situations) or a unique_ptr or even auto_ptr, which are safe and still allow the user to choose a different mechanism (i.e. if your function returns an auto_ptr, the user can still use a shared_ptr by doing shared_ptr<Base> p( f().release() );, while the opposite is not possible (memory managed by a shared_ptr cannot be released to use in a different smart pointer.
This quick-and-dirty return type adapter is good not only for converting return types from Derived* to Base*, but between any convertible types. For simplicity, the function-object takes no arguments. With C++11 variadic templates it should be easy to add arbitrary argument handling. Feel free to improve on this in any way you wish.
template <typename ToType>
class return_type_adapter
{
template <typename toType>
class return_type_adapter_impl_base
{
public:
virtual toType call() = 0;
};
template <typename toType, typename Func>
class return_type_adapter_impl : public return_type_adapter_impl_base<toType>
{
public:
return_type_adapter_impl (Func func) : func(func) {}
toType call() { return toType(func()); }
private:
Func func;
};
boost::shared_ptr<return_type_adapter_impl_base<ToType> > impl_base;
public:
ToType operator() () { return impl_base->call(); }
template <typename Func>
return_type_adapter (Func func) :
impl_base(new return_type_adapter_impl<ToType, Func>(func)) {}
};
map1["Derived1"] = boost::lambda::bind(
boost::lambda::constructor<boost::shared_ptr<Base>>(),
boost::lambda::bind(
boost::lambda::new_ptr<Derived1>()));
map1["Derived2"] = boost::lambda::bind(
boost::lambda::constructor<boost::shared_ptr<Base>>(),
boost::lambda::bind(
boost::lambda::new_ptr<Derived2>()));
But honestly, this is the level of complexity where it doesn't really make sense to use boost lambda any more. A simpler solution:
template<typename DerivedType>
boost::shared_ptr<Base> makeDerived() {
return boost::shared_ptr<Base>(new DerivedType);
}
[...]
map1["Derived1"] = makeDerived<Derived1>;
map1["Derived2"] = makeDerived<Derived2>;
Related
I built a class Interface to be used with CRTP for static polymorphism and a Client class having a shared_ptr to the Interface. I would like to return from the Client the shared_ptr to the Implementation, something that I can (safely?) do through static_pointer_cast within the Client. Is there a way to allow an implicit downcasting from the shared_ptr to Interface to a shared_ptr to Implementation?
template<class Implementation>
struct Interface {
int foo() { return static_cast<Implementation*>(this)->fooimpl();}
};
template<class Implementation>
struct Client {
Client(std::shared_ptr<Implementation> const & pt) : pt_{pt} {}
std::shared_ptr<Interface<Implementation>> pt_;
std::shared_ptr<Implementation> getPt() {
//Can I avoid this static_pointer_cast?<
return std::static_pointer_cast<Implementation>(pt_);
}
};
One possible solution to avoid all this mess is to keep a shared_ptr to Implementation within the Client class. In this way, however, nowhere I am saying that Implementation in Client has the Interface.
template<class Implementation>
struct Client {
Client(std::shared_ptr<Implementation> const & pt) : pt_{pt} {}
std::shared_ptr<Implementation> pt_;
std::shared_ptr<Implementation> getPt() { return pt_;}
};
Is there a way to allow an implicit downcasting from the shared_ptr to Interface to a shared_ptr to Implementation?
Simple answer: No! As the compiler have no idea of the "reverse" inheritance, it can give you direct support for it. CRTP is a general pattern to work around the underlying problem. Here the downcast is hand coded but hidden behind the interface of the CRTP implementation.
The CRTP is because I want Client to use foo() and at the same time independent of the implementation
As you get it as a compile time implementation, it is not really independent at the moment. You will see it latest, if you want point to something of that CRTP type.
The shared_ptr is because the Implementation may be shared among Clients
Your idea have a circular problem!
If you write as given in your example:
template
struct Client {
Client(std::shared_ptr const & pt) : pt_{pt} {}
std::shared_ptr pt_;
std::shared_ptr getPt() { return pt_;}
};
the code which calls getPt() must know the type of the returned pointer! Even if you use auto you will get the type of the returned pointer. So you simply can't hide it from your using code at all.
I ended up just putting a shared_ptr to the Implementation as class member and added a "static_assert + is_base_of " to insure this.
Seems to be also a circular problem.
If you write:
template < typename T>
class CRTP: public T
{
public:
void Check()
{
static_assert( std::is_base_of_v < T, CRTP<T> > );
}
};
class A {};
int main()
{
CRTP<A> x;
x.Check();
}
What is the assert helping here? It is only a check that you wrote 4 lines above "class CRTP: public T". For me that makes no sense.
I still have no real idea what you want to achieve more than simply using CRTP.
Consider this code
enum Types
{
t1,
t2
};
struct Base
{
Types typeTag;
Base(Types t) : typeTag(t){}
};
template<typename T>
struct Derived : Base
{
using Base::Base;
T makeT() { return T(); }
};
int main()
{
Base *b = new Derived<std::string>(t1);
auto d = getDerivedByTag(b); // How ??
d->makeT();
return 0;
}
Is it possible to restore Derived type parameter by Base::typeTag value in runtime? Obviously, some external preliminarily prepared mapping is needed, but I can't figure out the exact way.
What you want is basically a reflection that is not (yet) supported in C++. There are ways to simulate it or work around it but they are often verbose and not elegant. I would suggest rethinking your design, particularly your use of auto. It is not supposed to substitute for "any type" as you seem to imply by your code. It is meant as simplification of code when actual type is long or obfuscated (often happens with templates), nested etc. Not when you do not know the type! Because then you cannot really use it, can you.
So what you will have to do in one way or another is check the typeTag directly and continue based on that information. Alternatively you would need to use polymorphism using the Base directly (calling virtual methods propagated to Derived). For type unions you could use boost::variant (if you do not care what type Derived template argument is) or some other framework/library alternative like QVariant in Qt.
I'm not sure if my understanding is correct.
#include "iostream"
enum Types
{
t1,
t2
};
template<typename T>
struct Base
{
typedef T DerivedType;
Types typeTag;
Base(Types t) : typeTag(t){}
DerivedType* operator()() {
return static_cast<DerivedType*>(this);
}
};
template<typename T>
struct Derived : Base<Derived<T>>
{
Derived(Types t): Base<Derived<T>>(t) {}
T makeT() { return T(); }
};
int main()
{
Base<Derived<std::string>> *b = new Derived<std::string>(t1);
auto d = (*b)();
d->makeT();
return 0;
}
https://godbolt.org/g/uBsFD8
My implementation has nothing to do with typeTag.
Do you mean getDerivedByTag(b->typeTag) rather than getDerivedByTag(b)?
I'm subclassing std::shared_ptr and am trying to write a cast() method on the subclass so I can hide static_pointer_cast, but I can't get my code to compile. What am I missing?
Demo: http://ideone.com/nbPHbs
template<class T>
class Handle : public std::shared_ptr<T> {
public:
template<class ResultType>
inline Handle<ResultType>
cast() {
// Cast Handle to shared_ptr
auto T_sp = static_cast< std::shared_ptr<T> >(*this);
// Cast the data
auto ResultType_sp = std::static_pointer_cast<ResultType>(T_sp);
// Cast back to Handle
return static_cast< Handle<ResultType> >(ResultType_sp);
}
};
// Usage
struct Base {};
struct Child : public Base {};
auto child_ptr = Handle<Child>(new Child());
auto base_ptr = child_ptr.cast<Base>(); // Error with this
This is the Error message I get:
error: no matching function for call to 'Handle<Child>::Handle(Child*)'
auto child_ptr = Handle<Child>(new Child());
^
**EDIT
I'm using inheritance here because it was write-once/throw-away code that was originally template<T> using std::shared_ptr<T> Handle<T>; So, inheritance was the natural progression that required the least amount of code changes. Since it did look like this piece of code will stick around a little longer, I did switch to composition before posting this SO question, I just wanted to know why it wasn't compiling; I haven't done any c++ in a few years, so my skills are a little rusty.
This answer is skipping the discussion as to whether inheriting from std::shared_ptr is a good idea or not. I would though recommend reading such discussion before continuing further.
Now to your immediate problem:
If you really want to continue this route then what you are missing is the constructors.
The compiler is only creating a default constructor for you.
As the error message shows you need Handle<Child>::Handle(Child*).
The easiest way to get the needed constructors would be to reuse the ones from the base class:
template<class T>
class Handle : public std::shared_ptr<T> {
public:
using std::shared_ptr<T>::shared_ptr;
...
I dont see any advantage of inheriting shared_ptr here, its not worth the trouble imho. if you think std::static_pointer_cast is big and ugly, you can solve that by an inline function
template <typename TOUT, typename TIN>
inline std::shared_ptr<TOUT> cast(TIN in)
{
return std::static_pointer_cast<TOUT>(in);
}
// Usage
struct Base {};
struct Child : public Base {};
int main() {
std::shared_ptr<Child> child_ptr = std::make_shared<Child>();
std::shared_ptr<Base> base_ptr = cast<Base>(child_ptr); // Error with this
return 0;
}
Your class does not have any constructor, therefore, when you try to compile, it will miserably fail if you try to use a constructor with arguments.
If you wanted to inherit from shared_ptr (which I disencourage, because base destructor is not virtual and your program most likely will leak memory heavily) you should add this line in your class body:
using std::shared_ptr<T>::shared_ptr;
What is the proper way to allow vectors of shared pointers to a derived class to get passed to a function which is expecting a vector of shared pointers to a base class without performing a copy?
Here is the code:
#include <string>
#include <vector>
#include <memory>
class Base {
public:
std::string Name;
};
using BaseList = std::vector<std::shared_ptr<Base>>;
class Derived : Base {
};
using DerivedList = std::vector<std::shared_ptr<Derived>>;
class BaseHandler {
public:
void process( BaseList list ) {
}
};
int main() {
DerivedList list;
BaseHandler bh;
bh.process( list );
}
Code Link: http://coliru.stacked-crooked.com/a/5a5b18ba3b2a4f08
EDIT: DOH!!! I posted the wrong one. Sorry about that...here is the shared_ptr one.
You may try this.
template <class T,
class SharedPtr = typename T::value_type,
class Element = typename SharedPtr::element_type,
class IsDerived = typename std::enable_if<std::is_base_of<Base, Element>::value, void*>::type
>
void process(const T& t) { std::cout << "process" << std::endl; }
The key ideas are:
Instead of accessing the elements through base class pointers, we can access the them through their concrete type information known by the compiler.
This function template uses a trick called "SFINAE" to check whether the parameter is a container of smart pointer of derived class.
Follow up:
Conversion from "container of shared pointer to derived class" to "container of shared pointer to base class" is possible and not very difficult. However, I concern whether the design choice of using "container of shared pointer to base class" will give you acceptable performance.
Let's discuss how to do it first.
We can create a std::shared_ptr<Base> object from each std::shared_ptr<Derived> object by using std::static_pointer_cast.
To apply std::static_pointer_cast on everything entries of the list, we can use std::transform.
If you have many derived classes, the conversion can be made available to every derived classes by using a function template with SFINAE check as mentioned.
So, the code looks like:
DerivedList derivedList;
// Put items into derivedList
BaseList baseList;
baseList.reserve(derivedList.size());
std::transform(std::begin(derivedList), std::end(derivedList), std::back_inserter(baseList),
[](const std::shared_ptr<Derived>& shptr)
{
return std::static_pointer_cast<Base>(shptr);
});
BaseHandler bh;
bh.process(baseList);
Or:
class BaseForwarder
{
public:
template <class T,
class SharedPtr = typename T::value_type,
class Element = typename SharedPtr::element_type,
class IsDerived = typename std::enable_if<std::is_base_of<Base, Element>::value, void*>::type
>
void process(const T& derivedList)
{
BaseList baseList;
baseList.reserve(derivedList.size());
std::transform(std::begin(derivedList), std::end(derivedList), std::back_inserter(baseList),
[](const SharedPtr& shptr)
{
return std::static_pointer_cast<Base>(shptr);
});
BaseHandler bh;
bh.process(baseList);
}
};
However, this approach has quite a lot of performance penalty.
A new list of pointer to base class has to be created for each list of pointer to derived class. It spends a lot of time and memory to construct the new list.
The objects are accessed through pointers. This indirection slow things down.
Since the objects are not allocated into compact data structure, cache misses will be severe.
I suggest you to evaluate the performance to see whether this approach is acceptable. Otherwise, it is better to consider some other design choices.
I am trying to make a template class as placeholder class which can hold something like and string and type T object. Below is the code which I have written for the same.
#include <iostream>
#include <string>
#include <map>
using namespace std;
//A class which act as placeholder to hold
//unknown object. Something similar as Object
//in Java
template <typename T>
class Genric
{
public:
map<string, T> addP; //This will be placeholder for time
// being.
};
class A
{
public:
Genric t1; //Have object of Genric class so that we can
// access the member variable in future.
void foo()
{
cout<<"Calling foo"<<endl;
}
};
int main()
{
A a1;
a1.foo();
}
But when I tried to compile I am getting below error.
$ g++ tempClass.cxx
tempClass.cxx:21:9: error: invalid use of template-name 'Genric' without an argument list
The purpose of above Genric class is just to act as placeholder class for one of the member variables which can be populated in future.
So is there a way we can write such Genric class.
You are defining Genric as a template class, but then trying to initialize t1 without giving a type to it. That is the error you are getting. Try for example:
Genric<int> t1;
Or, if you are looking for a truly runtime generic, look into boost::any.
You need something like boost::any:
map<string, boost::any> anywayzz;
You can store any object in it. You don't need Genric class template.
If you're not using boost, then you can implement any yourself. Look for its implementation, or type-erasure, on this site. You will surely get some idea. Start from here:
Type erasure techniques
A template is "generic" until the program is compiled. At that point the compile must be made aware of what types it has to deal with.
If you want something that can contain a compile-time unknown (better: not yet known) type template are not the solution. Since the actual type will be known just at runtime, you have to go towards runtime-based polymorphism (inheritance from a polymorphic base) eventually wrapped inside an "handler".
In essence you need a base with at leas t a virtual function that allow you to check the type, and generic derived class that implement that function in a suitable way for all types.
boost::any can be an implementation, but there can be simpler ways, especially considering that "a function that allows to discover a runtime type" is no more than ... dynamic_cast.
You can so cometo a solution like this
#include <memory>
class any_value
{
template<class T>
class wrapper; //see below
class common_base
{
public:
virtual ~common_base() {} //this makes the type polymorphic
template<class T>
T* has_value()
{
auto* ptr = dynamic_cast<wrapper<T>*>(this);
return ptr? &ptr->m: nullptr;
}
};
template<class T>
class wrapper: public common_base
{
public:
wrapper() :m() {}
wrapper(const T& t) :m(t) {}
T m;
};
std::unique_ptr<common_base> pb;
public:
any_value() {}
template<class T>
any_value(const T& t) :pb(new wrapper<T>(t)) {}
template<class T>
any_value& operator=(const T& t)
{ pb = std::unique_ptr<common_base>(new wrapper<T>(t)); return *this; }
any_value(any_value&&) =default;
any_value& operator=(any_value&&) =default;
//NOW THE GETTERS
template<class T>
T* get() const //nullptr if not holding a T*
{ return bool(pb)? pb->has_value<T>(): nullptr; }
template<class T>
bool get(T& t)
{
T* pt = get<T>();
if(pt) t = *pt;
return bool(pt);
}
};
#include <iostream>
#include <string>
int main()
{
any_value a(5), b(2.7192818), c(std::string("as a string"));
int vi=0; double vd=0; std::string vs;
if(!a.get(vi)) vi=0; //will go
if(!a.get(vd)) vd=0; //will fail
if(!a.get(vs)) vs.clear(); //will fail
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
if(!b.get(vi)) vi=0; //will fail
if(!b.get(vd)) vd=0; //will go
if(!b.get(vs)) vs.clear(); //will fail
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
if(!c.get(vi)) vi=0; //will fail
if(!c.get(vd)) vd=0; //will fail
if(!c.get(vs)) vs.clear(); //will go
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
}
Following Abhinav comment:
Since the C++ type system is static, you cannot -in general- deserialize an "unknown", unless you first deserialize something that can be "Known".
For this you first need a way to represet a C++ type (not object) into an recognizable value (sort of type-uid), and a "factory" that creates the wrappers appropriated for those "values".
On saving, you just save that uid, then ask via a common_base virtual function to save the wrapped value.
On loading, you first load the uid, than create a new wrapper with appropriate type (see after) and than load the value via a common_base virtual function.
To create an appropriate wrapper, you need a table that maps the uid-s towards functions that create the wrapper associated with the type uid.
This table must be pre-initialized for all the types you need to be able to serialize / deserialize.
But this goes long away your original question, that doesn't speak about serialization/deserialization.
If the problem is "serialization", the "type erasure" is not a complete solution. You should much more look at the "factory pattern". And post another question better suited for that argument.