Templating static Create function - c++

I have following base class:
class Base abstract
{
public:
virtual ~Base() {};
protected:
Base() {};
virtual bool Initialize() abstract;
};
In extending classes that are not abstract I always define static Create function.
class Next : public Base
{
public:
static Next* Create(/*eventual params*/);
~Next() {};
protected:
Next(/*eventual params*/) {};
virtual bool Initialize() {/*...*/};
};
Create function looks always like this:
Next* Next::Create(/*eventual params*/)
{
bool succes;
Next* next = new Next(/*eventual params - same as above*/);
succes = next->Initialize();
if(!succes)
{
return NULL;
}
return next;
}
My question is; is it possible to shorten this function down? Using template for example or closing it in one line?

Just using templates in a function to create a generic class and call some function in it is simple, the problem you have is the /*eventual params*/ part. You can solve that with something called parameter packs, also called variadic templates.
Perhaps something like this:
template<typename T, typename ...A>
T* create(A... args)
{
T* object = new T(std::forward<A>(args)...);
if (object->Initialize())
return object;
delete object;
return nullptr;
}
With your example class Next can be used like
Base* pointer_to_next = create<Next>(/* eventual arguments */);
Of course, it requires C++11.

Related

How to iterate through all typenames in a class template?

I want to design a component-based weapon template for my game. However, it seems no way to add/remove a class member or create a code?
Sorry for my expression and lack of terminology, for I am not graduated from dept. of computer science or software engineer, I know little of what those stuff called by professionals.
Here is the component code looks like:
class CBaseWpnCmpt : public std::enable_shared_from_this<CBaseWpnCmpt>
{
public:
typedef std::shared_ptr<CBaseWpnCmpt> PTR;
private:
CBaseWpnCmpt() = default;
public:
CBaseWpnCmpt(const CBaseWpnCmpt& s) = default;
CBaseWpnCmpt(CBaseWpnCmpt&& s) = default;
CBaseWpnCmpt& operator=(const CBaseWpnCmpt& s) = default;
CBaseWpnCmpt& operator=(CBaseWpnCmpt&& s) = default;
virtual ~CBaseWpnCmpt() {}
protected:
CBaseWeaponInterface::PTR m_pWeapon { nullptr };
public:
template <class CComponent>
static std::shared_ptr<CComponent> Create(CBaseWeaponInterface::PTR pWeapon)
{
std::shared_ptr<CComponent> pComponent = std::make_shared<CComponent>();
pComponent->m_pWeapon = pWeapon;
return pComponent;
}
};
And this is what a weapon body code looks like: (And the problem occurs)
template < class CWeapon,
class ...CComponents
>
class CBaseWeaponTemplate : public CBaseWeaponInterface
{
public:
std::list<CBaseWpnCmpt::PTR> m_lstComponents;
public:
virtual void SecondaryAttack(void) // Example method.
{
for (auto& pComponent : m_rgpComponents)
{
pComponent->SecondaryAttack();
}
}
};
How am I suppose to create all these argument packs as member of the template? Currently I tried to enlist them into a pointer std::list container, but I just can't figure out how to achieve it at all.
In other words, how can I make a template when I fill in blank likt this:
class CAK47 : public CBaseWeaponTemplate<CAK47, CLongMagazine, CWoodenStock>
will generate this:
class CAK47
{
CLongMagazine m_comp1;
CWoodenStock m_comp2;
//... other stuff
};
Or alternatively, generate this:
class CAK47
{
CAK47() // constructor
{
for (/* somehow iterate through all typenames */)
{
CBaseWpnCmpt::PTR p = std::make_shared<typename>();
m_lstComponents.emplace_back(p);
}
}
};
One way of doing so from C++11 on-wards would be to store the template types used for this particular weapon inside an std::tuple
template <typename Weapon, typename... Attachments>
class WeaponWithAttachments {
protected:
WeaponWithAttachments() {
return;
}
std::tuple<Attachments...> attachment_types;
};
and then using that tuple to initialise a vector of shared pointers with a protected constructor taking a tuple to access the template types again.
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: SomeWeaponWithAttachments{attachment_types} {
return;
}
protected:
template <typename... Attachments>
SomeWeaponWithAttachments(std::tuple<Attachments...> const&)
: attachments{std::make_shared<Attachments>()...} {
return;
}
std::vector<std::shared_ptr<BaseAttachment>> attachments;
};
Try it here!
If the attachments vector is already declared inside the parent class like it seems to be the case for you might also avoid the tuple and the protected constructor with initialising the attachments already inside the parent class
template <typename Weapon, typename... Attachments>
class WeaponWithAttachments {
protected:
WeaponWithAttachments()
: attachments{std::make_shared<Attachments>()...} {
return;
}
std::vector<std::shared_ptr<BaseAttachment>> attachments;
};
and then only calling the constructor of the base class in the derived class
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment>() {
return;
}
};
Try it here!
If that is no option for you, then you can use the tuple to iterate over all the template arguments using C++17 fold expressions:
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: SomeWeaponWithAttachments{attachment_types} {
return;
}
protected:
template <typename... Attachments>
SomeWeaponWithAttachments(std::tuple<Attachments...> const&) {
(attachments.push_back(std::make_shared<Attachments>()), ...);
return;
}
};
Try it here!
In C++17 you might also add a static assertion with fold expressions into the constructor to make sure that the types actually inherit from BaseAttachment:
static_assert((std::is_base_of_v<BaseAttachment, Attachments> && ...), "Template arguments must inherit from 'BaseAttachment'.");

How to Change a C++ Class member's Type

Is it possible to be able to assign a "flexible" type to a class member? This would be somewhat like std::variant or std::any, except std::variant requires types to be stated in advance and std::any requires any_cast<Type> (which isn't a problem, except for saving the type information so I'd know what type to cast the std::any member to).
What I'm looking for is something that makes the following functionality possible:
class FlexType
{
ChangeableType m_Value;
public:
FlexType(SomeType init_value)
: m_Value(init_value)
{}
void setValue(SomeOtherType new_value) { m_Value = new_value; }
CurrentType getValue() const { return m_Value; }
};
Edit
I need the functionality for storing a return type of an std::function, where I want to be able to change the std::function's return type to any given type. This comes from a class that has a virtual void run() const method (call it "ParentClass" for convenience). I then have a child class that overrides the run() method and runs an std::function and saves the return value in another class member.
It looks something like this:
class ParentClass
{ // Example basic parent class
private:
/* ... Class members ... */
public:
ParentClass() = default;
virtual void run() const { /* Do stuff w/ class members */ }
};
template<class FuncRetTy, class... FuncArgs>
class ChildClass : public ParentClass
{
private:
using function_return_type = FuncRetTy;
using function_arg_types = FuncArgs...;
using function_args_container = std::tuple<function_arg_types>;
std::function<function_return_type(function_args_container)>
mutable function_return_type m_StoredValue;
function_type m_Function;
func_args_container m_Args;
public:
FunctionMenu(
function_return_type type_var, // Used to deduce return type
function_type function,
function_arg_types arguments)
: m_Function(function)
, m_Args(std::make_tuple(std::forward<FuncArgs>(arguments)...))
{}
void run() const override
{
m_StoredValue = m_Function(m_Args);
}
[[nodiscard]] function_return_type getStoredValue() const
{
return m_StoredValue;
}
// This is where my problem is...
// I want to be able to set m_Function to another function,
// but this means the return type can change, and so can
// the tuple template parameters for m_Args.
// The below code is just pseudocode
template<class NewFuncRetTy, class... NewFuncArgs>
void setFunction(
NewFuncRetTy type_var,
std::function<NewFuncRetTy(std::tuple<NewFuncArgs...>)> function
NewFuncArgs... args)
{
// Change all class typedef's to new types
// Reassign m_Function = function
// Reassign m_Args = make_tuple(std::forward<NewFuncArgs>(args)...);
// Delete whatever value m_StoredValue already has and
// change type of m_StoredValue to NewFuncRetTy so
// getStoredValue() knows what type to return
}
};
I'm sorry about there being a lot of code, but I figured explaining in detail what exactly I'm asking for would help people understand the question better.

C++ Function pointer arguments and classes inheritance automatic cast

First of all sorry if the name of the question is not clear enough. I really have no idea on how to call this problem.
So I have a function pointer inside a class that works like a java callback that I invoke with some parameters like itself that is derived from a parent class like in this example:
class Parent;
using f_Call = void(*)(Parent*);
class Parent
{
public:
void setCallback(f_Call call)
{
mOnCall = call;
}
protected:
f_Call mOnCall = nullptr;
};
class Child1 : Parent
{
public:
void doSomething()
{
// some work..
if (mOnCall)
mOnCall(this);
}
};
void onCallExe(Parent* p)
{
Child1* child = (Child1*)p;
// do some more work...
}
int main()
{
Child1 child;
child.setCallback(onCallExe);
child.doSomething();
}
My question is if does c++ has a way of doing the cast from parent to children automatically in onCallExe so I don't have to do it for every function I call.
Thank you!
Don't use function pointers. Instead, you want std::function<void()> (yes, without arguments) and pass it a lambda with a captured object.
using f_Call = std::function<void()>;
class Parent {
public:
void setCallback(f_Call call) {
mOnCall = call;
}
protected:
f_Call mOnCall;
};
class Child1 : public Parent {
public:
void doSomething() {
// some work..
if (mOnCall)
mOnCall(); // no argument!
}
};
int main() {
Child1 child;
child.setCallback([&child](){ /* do whatever with the child */ });
child.doSomething();
}
If you want, you can hide creation of the lambda in a function template.
template <class Obj, class CB>
void setCallback (Obj& obj, CB cb) {
obj.setCallback([&obj](){cb(obj);});
}
and then pass the global setCallback template any old function with a Child argument.
void onCallExe(Child1& child) {
// do some more work...
}
Child1 child;
setCallback(child, onCallExe);
Curiously recurring template pattern might be an option. However, you'll create separate base classes for each derived one, so you couldn't use them polymorphically – unless you provided a separate, common base. If the recurring template function overwrites a virtual one in the base, you might end up at where you wanted to get:
struct Base
{
virtual ~Base() { }
virtual void f() = 0;
};
template <typename T>
struct Intermediate : Base
{
void f() override
{
if(callback)
callback(static_cast<T*>(this));
}
void setCallback(void(*c)(T*))
{
callback = c;
}
private:
void(*callback)(T*) = nullptr;
};
struct Derived : Intermediate<Derived>
{
};
void g(Derived*) { }
void demo()
{
Derived d;
d.setCallback(g);
d.f();
}
(If you don't need polymorphism, you can skip Base class – then f doesn't have to be virtual either.)
Solely if you wanted to set the callbacks via pointer or reference to Base, you are a bit in trouble, as you cannot have virtual template member functions. You could, though provide a free-standing helper function:
template <typename T>
void setCallback(Base& b, void(*callback)(T*))
{
dynamic_cast<Intermediate<T>&>(b).setCallback(callback);
}
The dynamic cast will throw a std::bad_cast if b is of inappropriate type – unfortunately a rather costly run-time thing, a safe way to let the compiler determine if pointed/referred object is of correct type (usually) is not possible.

Create "new instance of object" method in C++

Is there a way to create an instance of a class, from that class, without using templates?
I need to do somethink like
static classobj* classobj::create (){return new this;}
Now I use class template and pass to template type of creatable class like :
template<class T>
class basic_class {
public:
static T *create(int param) { return new T(param); }
}
and
class A : public basic_class<A> {}
Why not this?
return new classobj;
Or this:
return new decltype(*this);
But please don't do this at all. The pointer returned by your function has unclear ownership semantics. We generally don't need raw pointers nowadays.
If I understand your question correctly, you want to create a non-template class like this:
class Base
{
public:
static (Magic)* create() { return new (Magic); }
}
We would then call this method thusly:
class Derived : public Base {};
Derived* object = Derived::create();
And the question is: what incantation do we substitute for "(Magic)?" Unfortunately, there is no such syntax. Static class methods are just like regular functions. All types involved must be known at the point the function is declared.
Can you elaborate on why you don't want to use templates? Perhaps there's another way to solve your problem.
If I understand your question correctly, then you have to add static create to every class:
class A
{
public:
//to create
static A* create(int param) { return new A(param); }
};
and then do this:
A* ptr = A::create(4);
or better, avoiding memory leaks
std::unique_ptr<A> uptr(A::create(4));
Or, if your issue is to make a "smart" create in the basic_class for any constructor, then do this in C++11:
template <class T>
class base_class
{
public:
template<typename... Params>
static T* construct(Params&&... parameters) { return new T(std::forward<Params>(parameters)...); }
};
class A : public base_class<A>
{
public:
A(const std::string& s) {}
A(int i) {}
};
and so
A::create(std::string("Hey"));
A::create(5);
both work now.
Edit: Base class defines "construct" method. So the above should be
A::construct(std::string("Hey"));
A::construct(5);
Implement a copy constructor first
classobj(const classobj& obj);
then
return new classobj(*this)

How can I use covariant return types with smart pointers?

I have code like this:
class RetInterface {...}
class Ret1: public RetInterface {...}
class AInterface
{
public:
virtual boost::shared_ptr<RetInterface> get_r() const = 0;
...
};
class A1: public AInterface
{
public:
boost::shared_ptr<Ret1> get_r() const {...}
...
};
This code does not compile.
In visual studio it raises
C2555: overriding virtual function return type differs and is not
covariant
If I do not use boost::shared_ptr but return raw pointers, the code compiles (I understand this is due to covariant return types in C++). I can see the problem is because boost::shared_ptr of Ret1 is not derived from boost::shared_ptr of RetInterface. But I want to return boost::shared_ptr of Ret1 for use in other classes, else I must cast the returned value after the return.
Am I doing something wrong?
If not, why is the language like this - it should be extensible to handle conversion between smart pointers in this scenario? Is there a desirable workaround?
Firstly, this is indeed how it works in C++: the return type of a virtual function in a derived class must be the same as in the base class. There is the special exception that a function that returns a reference/pointer to some class X can be overridden by a function that returns a reference/pointer to a class that derives from X, but as you note this doesn't allow for smart pointers (such as shared_ptr), just for plain pointers.
If your interface RetInterface is sufficiently comprehensive, then you won't need to know the actual returned type in the calling code. In general it doesn't make sense anyway: the reason get_r is a virtual function in the first place is because you will be calling it through a pointer or reference to the base class AInterface, in which case you can't know what type the derived class would return. If you are calling this with an actual A1 reference, you can just create a separate get_r1 function in A1 that does what you need.
class A1: public AInterface
{
public:
boost::shared_ptr<RetInterface> get_r() const
{
return get_r1();
}
boost::shared_ptr<Ret1> get_r1() const {...}
...
};
Alternatively, you can use the visitor pattern or something like my Dynamic Double Dispatch technique to pass a callback in to the returned object which can then invoke the callback with the correct type.
There is a neat solution posted in this blog post (from Raoul Borges)
An excerpt of the bit prior to adding support for mulitple inheritance and abstract methods is:
template <typename Derived, typename Base>
class clone_inherit<Derived, Base> : public Base
{
public:
std::unique_ptr<Derived> clone() const
{
return std::unique_ptr<Derived>(static_cast<Derived *>(this->clone_impl()));
}
private:
virtual clone_inherit * clone_impl() const override
{
return new Derived(*this);
}
};
class concrete: public clone_inherit<concrete, cloneable>
{
};
int main()
{
std::unique_ptr<concrete> c = std::make_unique<concrete>();
std::unique_ptr<concrete> cc = c->clone();
cloneable * p = c.get();
std::unique_ptr<clonable> pp = p->clone();
}
I would encourage reading the full article. Its simply written and well explained.
You can't change return types (for non-pointer, non-reference return types) when overloading methods in C++. A1::get_r must return a boost::shared_ptr<RetInterface>.
Anthony Williams has a nice comprehensive answer.
What about this solution:
template<typename Derived, typename Base>
class SharedCovariant : public shared_ptr<Base>
{
public:
typedef Base BaseOf;
SharedCovariant(shared_ptr<Base> & container) :
shared_ptr<Base>(container)
{
}
shared_ptr<Derived> operator ->()
{
return boost::dynamic_pointer_cast<Derived>(*this);
}
};
e.g:
struct A {};
struct B : A {};
struct Test
{
shared_ptr<A> get() {return a_; }
shared_ptr<A> a_;
};
typedef SharedCovariant<B,A> SharedBFromA;
struct TestDerived : Test
{
SharedBFromA get() { return a_; }
};
Here is my attempt :
template<class T>
class Child : public T
{
public:
typedef T Parent;
};
template<typename _T>
class has_parent
{
private:
typedef char One;
typedef struct { char array[2]; } Two;
template<typename _C>
static One test(typename _C::Parent *);
template<typename _C>
static Two test(...);
public:
enum { value = (sizeof(test<_T>(nullptr)) == sizeof(One)) };
};
class A
{
public :
virtual void print() = 0;
};
class B : public Child<A>
{
public:
void print() override
{
printf("toto \n");
}
};
template<class T, bool hasParent = has_parent<T>::value>
class ICovariantSharedPtr;
template<class T>
class ICovariantSharedPtr<T, true> : public ICovariantSharedPtr<typename T::Parent>
{
public:
T * get() override = 0;
};
template<class T>
class ICovariantSharedPtr<T, false>
{
public:
virtual T * get() = 0;
};
template<class T>
class CovariantSharedPtr : public ICovariantSharedPtr<T>
{
public:
CovariantSharedPtr(){}
CovariantSharedPtr(std::shared_ptr<T> a_ptr) : m_ptr(std::move(a_ptr)){}
T * get() final
{
return m_ptr.get();
}
private:
std::shared_ptr<T> m_ptr;
};
And a little example :
class UseA
{
public:
virtual ICovariantSharedPtr<A> & GetPtr() = 0;
};
class UseB : public UseA
{
public:
CovariantSharedPtr<B> & GetPtr() final
{
return m_ptrB;
}
private:
CovariantSharedPtr<B> m_ptrB = std::make_shared<B>();
};
int _tmain(int argc, _TCHAR* argv[])
{
UseB b;
UseA & a = b;
a.GetPtr().get()->print();
}
Explanations :
This solution implies meta-progamming and to modify the classes used in covariant smart pointers.
The simple template struct Child is here to bind the type Parent and inheritance. Any class inheriting from Child<T> will inherit from T and define T as Parent. The classes used in covariant smart pointers needs this type to be defined.
The class has_parent is used to detect at compile time if a class defines the type Parent or not. This part is not mine, I used the same code as to detect if a method exists (see here)
As we want covariance with smart pointers, we want our smart pointers to mimic the existing class architecture. It's easier to explain how it works in the example.
When a CovariantSharedPtr<B> is defined, it inherits from ICovariantSharedPtr<B>, which is interpreted as ICovariantSharedPtr<B, has_parent<B>::value>. As B inherits from Child<A>, has_parent<B>::value is true, so ICovariantSharedPtr<B> is ICovariantSharedPtr<B, true> and inherits from ICovariantSharedPtr<B::Parent> which is ICovariantSharedPtr<A>. As A has no Parent defined, has_parent<A>::value is false, ICovariantSharedPtr<A> is ICovariantSharedPtr<A, false> and inherits from nothing.
The main point is as Binherits from A, we have ICovariantSharedPtr<B>inheriting from ICovariantSharedPtr<A>. So any method returning a pointer or a reference on ICovariantSharedPtr<A> can be overloaded by a method returning the same on ICovariantSharedPtr<B>.
Mr Fooz answered part 1 of your question. Part 2, it works this way because the compiler doesn't know if it will be calling AInterface::get_r or A1::get_r at compile time - it needs to know what return value it's going to get, so it insists on both methods returning the same type. This is part of the C++ specification.
For the workaround, if A1::get_r returns a pointer to RetInterface, the virtual methods in RetInterface will still work as expected, and the proper object will be deleted when the pointer is destroyed. There's no need for different return types.
maybe you could use an out parameter to get around "covariance with returned boost shared_ptrs.
void get_r_to(boost::shared_ptr<RetInterface>& ) ...
since I suspect a caller can drop in a more refined shared_ptr type as argument.