I have a situation that I am attempting to write some c++ code to implement and I think I need to use templates but I am unsure. I don't think I understand templates well enough and just want to know if I am on the right track. I have never implemented a class that requires templates before.
I have a base class that needs to instantiate a new class and store it on a list for future access. The class that needs to be instantiated is derived from a base class that has one virtual method. After the class is instantiated, this method is called and the new instance is stored on a list. Another method is provided to get the instantiated object.
Say the virtual class is named foo:
class foo
{
public:
virtual void process() = 0;
}
the user would create a class bar:
class bar : public foo
{
public:
void process() {};
}
The class that I think needs to be a template class:
class Filter<Foo* T>
{
public:
// use value junk to derive foo
// and put the new instance on a std::list
add(Junk* junk);
T get();
private:
std::list<T> mFooList;
}
void Filter::add(Junk* junk)
{
T* foo = new T();
foo.p(junk);
mFooList.push_back(foo);
}
T* Filter::get()
{
if(!mFoolist.empty())
{
T* res = mFooList.back();
mFooList.pop_back();
return res;
}
return nullptr;
}
You don't need to use a templatevin this situation. In c++ a derived class can be assigned to a pointer of the base class. You can just use foo pointers.
class foo
{
public:
virtual void process();
};
class bar1: public foo
{
public:
void process();
};
class bar2 : public foo
{
public:
void process();
};
class filter
{
private:
std::list<foo*> _foos;
public:
foo* get();
void add(foo* f);
};
void filter::add(foo* f)
{
_foos.push_back(f);
}
foo* filter::get()
{
if(!_foos.empty())
{
return _foos.pop_back();
}
return nullptr;
}
You can then just add and get foos and bars
filter fil;
fil.add(new foo());
fill.add(new bar1());
fill.add(new bar2());
foo f = fill.get();
while(f != nullptr)
{
f->process();
delete f;
f = fil.get();
}
Related
class Base
{
public:
virtual void foo() = 0;
};
class A : public Base
{
public:
void foo() override { std::cout << "A\n"; }
};
class B : public Base
{
public:
void foo() override { std::cout << "B\n"; }
};
class Registry
{
public:
static Registry& instance()
{
static Registry s_instance;
return s_instance;
}
void register_foo(Base* foo)
{
m_vec.emplace_back(foo);
}
private:
std::vector<Base*> m_vec;
};
template<typename ... T>
class Foo : public T...
{
public:
Foo()
{
Registry::instance().register_foo(this);
}
void test() { (T::foo(), ...); }
};
int main()
{
auto f1 = std::make_unique<Foo<A, B>>();
auto f2 = std::make_unique<Foo<A>>();
f1->test();
f2->test();
}
As you can see I have a Base class, class A and class B.
A and B inherit from Base.
Class Foo is a template class, which is with a variadic template.
The idea is to be able to pass class A and class B into Foo.
Then this Foo is registered in the Registry class / pushed into a vector.
The problem is the following - as you can see I can have both Foo<A> and Foo<A, B>, or Foo<B, A>.
How can I have such a vector which can accept all possible types of Foo?
How about a simple common base class?
class FooBase {
public:
virtual ~FooBase() {}
virtual void test() = 0;
};
template<typename... T>
class Foo : public FooBase, public T...
{
public:
Foo() { }
void test() override { (T::foo(), ...); }
};
int main()
{
auto f1 = std::make_unique<Foo<A, B>>();
auto f2 = std::make_unique<Foo<A>>();
std::vector<std::unique_ptr<FooBase>> foos;
foos.push_back(std::move(f1));
foos.push_back(std::move(f2));
}
A std::vector holds one type of objects. You cannot put objects of different types into the same vector (and objects created from a template with different template arguments are different types).
One option (I'd not recommend it) is having a vector that holds instances of std::any) - works, but cumbersome and inefficient to work with. Another option is a vector of pointers to a common base class and taking advantage of polymorphism. A third option is simply having sepperate vectors for each type of object.
I wanted to know if anyone knows of a way to force a class hierarchy to be constructible only by the factory, effectively prohibiting the direct use of std::make_shared outside of that factory.
In the example below I have Node as the base class and SceneNode as one of the many derived classes. Node contains a static member function create() which should be the factory and only way to create new instances of Node-derived classes.
#include <iostream>
#include <memory>
class Node {
public:
template <class T, class... Args>
static std::shared_ptr<T> create(Args&&... args)
{
static_assert(std::is_base_of<Node, T>::value, "T must derive from Node");
std::shared_ptr<T> node = std::make_shared<T>(std::forward<Args>(args)...);
return node;
}
protected:
Node() {}
};
class SceneNode : public Node {
public:
SceneNode() : Node()
{
}
};
int main() {
auto a = Node::create<SceneNode>(); // Should be the only way
auto b = std::make_shared<SceneNode>(); // Should be forbidden
}
The classic way of making your factory the only class able to instanciate a given class is to make your class constructor private, and making your factory friend of your class:
class Foo
{
friend class FooFactory;
private:
Foo() = default;
};
class FooFactory
{
public:
static Foo* CreateFoo() { return new Foo(); }
static void DestroyFoo(Foo* p_toDestroy) { delete p_toDestroy; }
};
int main()
{
// Foo foo; <== Won't compile
Foo* foo = FooFactory::CreateFoo();
FooFactory::DestroyFoo(foo);
return 0;
}
EDIT (With some inheritance):
#include <type_traits>
class Foo
{
friend class FooBaseFactory;
protected:
Foo() = default;
};
class Bar : public Foo
{
friend class FooBaseFactory;
protected:
Bar() = default;
};
class FooBaseFactory
{
public:
template <typename T>
static T* Create()
{
static_assert(std::is_base_of<Foo, T>::value, "T must derive from Foo");
return new T();
}
template <typename T>
static void Destroy(T* p_toDestroy)
{
static_assert(std::is_base_of<Foo, T>::value, "T must derive from Foo");
delete p_toDestroy;
}
};
int main()
{
// Foo foo; <== Won't compile
Foo* foo = FooBaseFactory::Create<Foo>();
FooBaseFactory::Destroy<Foo>(foo);
// Bar bar; <== Won't compile
Bar* bar = FooBaseFactory::Create<Bar>();
FooBaseFactory::Destroy<Bar>(bar);
return 0;
}
One solution to this problem is to create a type that only the factory can instantiate, and have an instance of that class be required to construct the base type. You can establish a convention where the first constructor argument for types that derive from Node is a value of or reference to that type which is fed to Node's constructor. Since it's not possible for anyone else to have a NodeKey users can't instantiate anything that derives from Node without going through the factory.
#include <memory>
#include <utility>
// Class that can only be instantiated by the factory type
class NodeKey {
private:
NodeKey() {};
friend class Factory;
};
class Factory {
public:
template<class T, class ... Args>
auto make(Args&&... args) {
auto ptr = std::make_shared<T>(NodeKey{}, std::forward<Args>(args)...);
// Finish initializing ptr
return ptr;
}
};
class Node {
public:
// Can only be called with an instance of NodeKey
explicit Node(const NodeKey &) {};
};
class Foo : public Node {
public:
// Forwards the instance
explicit Foo(const NodeKey & key) : Node(key) {};
};
int main()
{
Factory factory;
auto f = factory.make<Foo>();
}
My code structure is like below where multiple classes implement Interface. In Example class I store a pointer to the Interface and new() it in the constructor appropriately (depending on constructor parameters not shown here). I'm looking for ways to avoid using new() in this scenario but haven't got a solution yet. What's the best practice for something like this?
class Interface
{
virtual void Foo() = 0;
};
class A : public Interface
{
void Foo() { ... }
};
class B : public Interface
{
void Foo() { ... }
};
class Example
{
private:
Interface* m_bar;
public:
Example()
{
m_bar = new A(); // deleted in destructor
}
};
There are two ways this is typically done, each with their own merits.
If A is truely defined at compile time, than a typical way to handle this is to simply use a template type:
template <typename T>
class TemplateExample
{
T m_bar;
public:
TemplateExample() : m_bar() {};
}
This has some downsides. TemplateExample<A> becomes unrelated to TemplateExample<B>, the error messages when T doesn't follow the correct interface are pretty obtuse, ect. The upside is this may use duck typing rather than interface typing, and m_bar is a concrete instance.
The other (arguable more common) way is to do the following
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
};
This has the benefit of being able to be run time configuratble if you follow a cloable pattern:
class Interface
{
public:
virtual void Foo() = 0;
virtual Interface* clone() const = 0;
};
template <typename T>
class CloneHelper : public Interface
{
public:
virtual Interface* clone() const { return new T(static_cast<const T&>(*this));}
};
class A : public CloneHelper<A>
{
virtual void Foo() { std::cout << 'A' << std::endl; }
};
class B : public CloneHelper<B>
{
virtual void Foo() { std::cout << 'B' << std::endl; }
};
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
UniquePtrExample(const Interface& i) : m_bar(i.clone());
};
Note you can further extend the above to have a move variant of the clone function.
This question is regarding copying and pointer polymorphism. Consider the code below. We have two classes: Base and Derived, which are just regular objects. Then we've got class Foo, which has a pointer to Base as its only member.
The typical usage of Foo is described in the main function. The input to Foo::SetMemberX may or may not be a temporary object.
The problem is that I want Foo::SetMember to create a proper copy of the passed object, and assign its address as a Base* to Foo::mMember.
I've managed to come up with 4 possible solution, none of which seem very elegant to me. The first three are shown in the code below in Foo::SetMember1, Foo::SetMember2, and Foo::SetMember3. The 4th option is to leave the memory allocation to the user (ex. foo.SetMember(new Derived())), which is not very desirable for obvious memory safety issues. Foo should be responsible for memory management, not the user.
#include <iostream>
template <typename tBase, typename tPointer>
void ClonePointer(tBase*& destination, const tPointer* pointer)
{
destination = static_cast<tBase*>(new tPointer(*pointer));
}
// Base can be a virtual class
class Base
{
public:
virtual void Function()
{
std::cout << "Base::Function()" << std::endl;
}
virtual Base* Clone() const = 0;
};
class Derived : public Base
{
public:
virtual void Function()
{
std::cout << "Derived::Function()" << std::endl;
}
virtual Base* Clone() const
{
return new Derived(*this);
}
};
class Foo
{
public:
Foo() : mMember(NULL) { }
~Foo()
{
if (mMember != NULL)
{
delete mMember;
mMember = NULL;
}
}
template <typename T>
void SetMember1(const T& t)
{
if (mMember != NULL)
{
delete mMember;
mMember = NULL;
}
ClonePointer(mMember, &t);
}
void SetMember2(const Base& b)
{
mMember = b.Clone();
}
template <typename T>
void SetMember3(const T& t)
{
if (mMember != NULL)
{
delete mMember;
mMember = NULL;
}
mMember = new T(t);
}
Base& GetMember()
{
return *mMember;
}
private:
Base* mMember;
};
int main(int argc, char** argv)
{
{
Foo f1;
Foo f2;
Foo f3;
// The input may or may not be a tempoary/RValue reference
f1.SetMember1(Derived());
f2.SetMember2(Derived());
f3.SetMember3(Derived());
f1.GetMember().Function();
f2.GetMember().Function();
f3.GetMember().Function();
}
// Output:
// Derived::Function();
// Derived::Function();
// Derived::Function();
system("pause"); // for quick testing
}
The problem with the first method (Foo::SetMember1) is that I have a random, free, template function, and a template accessore (see the problem with the third method below).
The problem with the second method (Foo::SetMember2) is that every derived class must implement its own Clone function. This is too much boilerplate code for the class user, as there will be a lot of classes deriving from Base. If I could somehow automate this, or create a base Cloneable class (without each Base-derived class having to explicitly calling it) with an implemented template Clone function, this would be the ideal solution.
The problem with the third method (Foo::SetMember3) is that I'd need a template accessor for Foo. This may not always be possible, especially because of how virtual template methods are not allowed in non-template classes (Foo cannot be a template itself), which is a functionality that might be required.
My questions are:
Are these the only options I have?
Is there a better, more elegant solution to this problem that I'm missing?
Is there any way to create a base Cloneable class and derive Base from it, and have cloning automagically happen for DerivedType::Clone()?
Here's a more or less robust Clonable class that can be inherited to any depth. It uses CRTP and Alecsandrescu-style interleaving inheritance pattern.
#include <iostream>
// set up a little named template parameters rig
template <class X> struct Parent{};
template <class X> struct Self{};
template<class A, class B> struct ParentChild;
// can use ...< Parent<X>, Self<Y> >...
template<class A, class B> struct ParentChild< Parent<A>, Self<B> >
{
typedef A parent_type;
typedef B child_type;
};
// or ...< Self<Y>, Parent<X> >
template<class A, class B> struct ParentChild< Self<B>, Parent<A> >
{
typedef A parent_type;
typedef B child_type;
};
// nothing, really
struct Nada
{
// except the virtual dtor! Everything clonable will inherit from here.
virtual ~Nada() {}
};
// The Clonable template. Accepts two parameters:
// the child class (as in CRTP), and the parent class (one to inherit from)
// In any order.
template <class A, class B = Parent<Nada> > class Clonable :
public ParentChild<A,B>::parent_type
{
public:
// a nice name to refer to in the child class, instead of Clonable<A,B>
typedef Clonable Parent;
// this is our child class
typedef typename ParentChild<A,B>::child_type child_type;
// This is the clone() function returning the cloned object
// Non-virtual, because the compiler has trouble with covariant return
// type here. We have to implemens something similar, by having non-virtual
// that returns the covariant type calling virtual that returns the
// base type, and some cast.
child_type* clone()
{
return static_cast<child_type*>(private_clone());
}
// forward some constructor, C++11 style
template<typename... Args> Clonable(Args&&... args):
ParentChild<A,B>::parent_type(args...) {}
private:
// this is the main virtual clone function
// allocates the new child_type object and copies itself
// with the copy constructor
virtual Nada* private_clone()
{
// we *know* we're the child_type object
child_type* me = static_cast<child_type*>(this);
return new child_type(*me);
};
};
// Test drive and usage example
class Foo : public Clonable < Self<Foo> >
{
public:
Foo (int) { std::cout << "Foo::Foo(int)\n"; }
Foo (double, char) { std::cout << "Foo::Foo(double, char)\n"; }
Foo (const Foo&) { std::cout << "Foo::Foo(Foo&)\n"; }
};
class Bar : public Clonable < Self<Bar>, Parent<Foo> >
{
public:
// cannot say Bar (int i) : Foo(i), unfortunately, because Foo is not
// our immediate parent
// have to use the Parent alias
Bar (int i) : Parent(i)
{ std::cout << "Bar::Bar(int)\n"; }
Bar (double a, char b) : Parent(a, b)
{ std::cout << "Bar::Bar(double, char)\n"; }
Bar (const Bar& b) : Parent(b)
{ std::cout << "Bar::Bar(Bar&)\n"; }
~Bar() { std::cout << "Bar::~Bar()\n"; }
};
int main ()
{
Foo* foo1 = new Bar (123);
Foo* foo2 = foo1->clone(); // this is really a Bar
delete foo1;
delete foo2;
}
For 2nd method, you can use CRTP and you won't need to write clone method in every derived class:
struct Base {
virtual ~Base() {}
virtual Base *clone() const = 0;
};
template <typename Derived>
struct CloneableBase : public Base {
virtual Base *clone() const {
return new Derived(static_cast<Derived const&>(*this));
}
};
struct Derived: CloneableBase<Derived> {};
I'm refactoring a single 3000+-line class with a tangled web of conditionals and switches into a set of worker classes. Previously part of the constructor would select which "type" of thing to use via code like the following:
enum Type { FOO, BAR, BAZ };
Type choices[] = { FOO, FOO, BAR, BAZ }; // weighted towards FOO
m_type = choices[rand()%4];
[...later...]
void Run() {
switch (m_type) {
case FOO: do_foo(); break;
case BAR: do_bar(); break;
case BAZ: do_baz(); break;
}
}
After refactoring I have separate TypeFoo, TypeBar and TypeBaz classes that each have their own Run() methods to do their job. Sadly, its complicated the class selection code. I don't know of any way to keep a list of possible classes to construct, so I have this:
Type *m_type;
switch (mrand()%4) {
case 0: case 1: m_type = new TypeFoo(); break;
case 1: m_type = new TypeBar(); break;
case 2: m_type = new TypeBaz(); break;
}
This is still worth the change because this initialisation code is not called regularly, but its now harder to modify this list, change weightings, etc.
Is there a relatively straightforward to achieve the clarity of the original code?
The answer is : a base class and an array of function pointers can help you do that.
struct Base { virtual ~Base() {} }; //make ~Base() virtual
struct Foo : Base {};
struct Bar : Base {};
struct Baz : Base {};
template<typename T>
Base *Create() { return new T(); }
typedef Base* (*CreateFn)();
CreateFn create[] =
{
&Create<Foo>,
&Create<Foo>, // weighted towards FOO
&Create<Bar>,
&Create<Baz>
};
const size_t fncount = sizeof(create)/sizeof(*create);
Base *Create()
{
return create[rand() % fncount](); //forward the call
}
Then use it as (ideone demo):
int main() {
Base *obj = Create();
//work with obj using the common interface in Base
delete obj; //ok,
//the virtual ~Base() lets you do it
//in a well-defined way
return 0;
}
I would suggest creating a common base class (if you've not already got one) and then using a factory class to encapsulate the creation process. The factory would just return a pointer to your base class which has the prototype run method.
Something along these lines:
class Type
{
virtual void Run() = 0;
};
class TypeFoo : public Type
{
public:
TypeFoo() {};
virtual void Run() {};
static Type* Create() { return new TypeFoo(); };
};
class TypeBar : public Type
{
public:
TypeBar() {};
virtual void Run() {};
static Type* Create() { return new TypeBar(); };
};
class TypeBaz : public Type
{
public:
TypeBaz() {};
virtual void Run() {};
static Type* Create() { return new TypeBaz(); };
};
class TypeFactory
{
typedef Type* (*CreateFn)();
public:
static Type* RandomTypeFooWeighted()
{
CreateFn create[] =
{
TypeFoo::Create,
TypeFoo::Create, // weighted towards FOO
TypeBar::Create,
TypeBaz::Create
};
const int fncount = sizeof(create)/sizeof(*create);
return create[ rand()%fncount ]();
}
};
So to use it you can just call:
Type *t = TypeFactory::RandomTypeFooWeighted();
Credit to Nawaz for the function pointer bits and bobs.