I have a C++ library which is a wrapper for a C library. A factory class Creator
creates objects of which each represents parts of the functionality of the C library. These class constructors are private to ensure that all objects are created through that Creator
class because the C library requires some internal magic (which I omitted in the following, simplified example).
It all works, but I have the following "problem":
In class UsesAandB
I have to specify the template parameter of A<>
twice: Once in the member declaration ( std::shared_ptr<A<int>>
) and once in the initialization list of the constructor ( creator->createA<int>
).
Since I already know that member aInt
will be of type std::shared_ptr<A<int>>
, how can I use this knowledge to call the corresponding createA<int>()
method in the constructor without repeating int
or how can I avoid the call to createA<int>()
at all?
#include <memory>
class Creator;
template<typename T>
class A
{
friend class Creator;
private:
A(int param) {}
T value;
};
class B
{
friend class Creator;
private:
B(){}
};
class Creator
{
public:
template<typename T>
std::shared_ptr<A<T>> createA(int param) { return std::shared_ptr<A<T>>(new A<T>(param)); }
std::shared_ptr<B> createB() { return std::shared_ptr<B>(new B());}
};
class UsesAandB
{
public:
UsesAandB(std::shared_ptr<Creator> creator)
: creator(creator),
aInt(creator->createA<int>(0)),
aDouble(creator->createA<double>(1)),
b(creator->createB())
{
}
private:
std::shared_ptr<Creator> creator;
std::shared_ptr<A<int>> aInt;
std::shared_ptr<A<double>> aDouble;
std::shared_ptr<B> b;
};
int main()
{
auto creator = std::make_shared<Creator>();
UsesAandB u(creator);
return 0;
}
To get the type from the shared_ptr
, you need to pass it to a template function like this one:
template <typename U>
shared_ptr< A<U> > CreateA( std::shared_ptr<Creator>& c,
const shared_ptr< A<U> >& p,
const U& val )
{
return c->createA<U>(val);
}
Then simply:
aInt(CreateA(creator, aInt, 0 )),
Sample here - http://ideone.com/Np7f8t
My idea, don't know if it solves anything, but you do eliminate the chance of having different types in the declaration and constructor call.
template<typename T>
class A
{
friend class Creator;
private:
typedef T type;
A(int param) {}
T value;
};
class UsesAandB
{
typedef std::shared_ptr<A<int>> sharedA;
public:
UsesAandB(std::shared_ptr<Creator> creator)
: creator(creator),
aInt(creator->createA<sharedA::element_type::type>(0)),
aDouble(creator->createA<double>(1)),
b(creator->createB())
{
}
private:
std::shared_ptr<Creator> creator;
sharedA aInt;
std::shared_ptr<A<double>> aDouble;
std::shared_ptr<B> b;
};
You could add the following static template function
template <class T>
static std::shared_ptr<T> create1(std::shared_ptr<Creator> &creator, std::shared_ptr<T> &,T value)
{
return creator->createA(value) ;
}
An then initialize like this:
UsesAandB(std::shared_ptr<Creator> creator)
: creator(creator),
aInt(create1((creator, aInt, 0)),
aDouble(create1(creator, aDouble, 1)),
b(creator->createB())
{
}
create1 requires the shared pointer only to deduce the right type. A problem is that this code should raise a warning (this used in nitializer list)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.