How to combine multiple variadic templated tuple classes into one class? - c++

I have changed my approach from my original question to templatize the entire class instead and place it inside a variadic tuple. I can now use getters and setters the way that I would like them to be created. However, now I am trying to take it a step forward and combine the individual controllers into one controller.
#ifndef CONTROLLER_HPP
#define CONTROLLER_HPP
#include <functional>
#include <vector>
#include <iostream>
#include <utility>
template<typename...Classes>
class Controller
{
public:
Controller(Classes&...objects) : objects(objects...){}
void setValues(int value)
{
std::apply([&](auto&...x) { (x.updateValue(value),...);}, objects);
}
void getValues(std::vector<int> &values)
{
std::apply([&](auto&...x) { (values.push_back(x.get()),...);}, objects);
}
private:
std::tuple<Classes&...> objects;
};
#endif
With this I can do the following:
classA A;
classB B;
classC C;
classD D;
classE E;
classF F;
classG G;
Controller controller1(A,B,C);
Controller controller2(D,E);
Controller controller3(F,G);
controller1.setValues(20);
controller2.setValues(13);
controlelr3.setValues(32);
However, I want to take it a step further and combine the two like so:
Controller master(controller1,controller2,controller3);
master.setValues(40);
I have looked at this post talking about joining variadic templates, however I think this returns a type(?) and not a class. I also tried creating two overloaded classes, however I don't think I am creating the overload correctly:
template<typename...Classes>
class Controller
{
public:
Controller(Classes&...objects) : objects(objects...){}
void setValues(int value)
{
std::apply([&](auto&...x) { (x.updateValue(value),...);}, objects);
}
void getValues(std::vector<int> &values)
{
std::apply([&](auto&...x) { (values.push_back(x.get()),...);}, objects);
}
private:
std::tuple<Classes&...> objects;
};
template<Controller<typename ... > class Controllers, typename ...Classes>
class Controller<Controllers<Classes&...classes>...>
{
// create a new controller that takes all the combined classes
};
How can I combine any number of templated variadic templated classes into one class? I do have the ability to use C++17.

template<typename...Classes>
class Controller
{
Controller( std::tuple<Classes&...> tup ):objects(tup) {}
public:
template<class...Rhs>
Controller<Classes..., Rhs...> operator+( Controller<Rhs...> rhs ) const {
return std::tuple_cat( objects, rhs.objects );
}
...
giving us:
Controller master = controller1+controller2+controller3;
master.setValues(40);

Related

Apply functions belonging to other classes through variadic templates

Say I have three classes, ClassA, ClassB, and ClassC. And all three of these classes have a function called updateValue(int). And then I have controller class called, Controller. Who's constructor is templated like the following:
class Controller
{
public:
template <class...Classes>
Controller(Classes & ...classes); // maybe initialize a tuple?
void setValues(int val)
{
// unpack whatever data structure and call each classes updateValue(int)
}
private:
std::tuple<Classes...classes> packedClasses; // Not sure if this is good idea? This will not compile
};
As you can see, I want to be able to take the classes from some data structure, and call their functions. For example, in main I would have:
int main()
{
ClassA A;
ClassB B;
ClassC C;
Controller controller1(A,B);
Controller controller2(A,C);
Controller controller3(B,C);
Controller controller4(A,B,C);
controller4.setValues(20);
}
Each class has their own way of updating a value, for example ClassA has setValue(int), ClassB has setInt(int), and ClassC has updateNumber(int). My plan is to write the function updateValue into each of these classes that will call their setter functions. However, I am not sure how to achieve what it is I am trying to do. How can I unpack all of the classes and call their function updateValue(int)?
From your current interface, you might do something like:
class Controller
{
public:
template <class...Classes>
Controller(Classes&... classes)
{
mF = [&](int val) { (classes.updateValue(val), ...); }; // Fold expression from C++17
}
void setValues(int val)
{
mF(val);
}
private:
std::function<void(int)> mF;
};

How to store templated objects of different type in container?

Assuming I have a vector (or list or whatever container might be more suitable here) that I would like to store multiple objects (or pointers) of a templated type in:
std::vector<MyClass<double>> v;
// std::vector<MyClass<double> *> v;
Unfortunately, I want to store different templated objects in this container (and I need to access them ideally at constant time).
My first intuition was to create some sort of WrapperClass around MyClass that would internally manage any MyClass as a member variable, but it's not clear to me how I could pass along the appropriate type through to MyClass:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <vector>
using namespace std;
template<typename T>
class MyClass
{
public:
MyClass() {}
~MyClass() {}
};
// templating this of course works, but it doesn't solve my problem
template<typename T>
class WrapperClass
{
public:
WrapperClass()
{
m_object = MyClass<T>();
}
~WrapperClass() { }
private:
MyClass<T> m_object;
};
int main()
{
WrapperClass<bool> tmp = WrapperClass<bool>();
std::vector<WrapperClass<bool> *> v;
return 0;
}
So is there (A) a different container than vector that I could be using for this problem or (B) a way to select the type of MyClass in WrapperClass inside the constructor? I was thinking of something along the lines of:
class WrapperClass2
{
public:
WrapperClass2(unsigned int typeId)
{
switch (typeId)
{
case 0: m_object = new MyClass<bool>();
case 1: m_object = new MyClass<int>();
case 2: m_object = new MyClass<float>();
default: m_object = new MyClass<double>();
}
}
~WrapperClass2()
{
delete m_object;
}
private:
MyClass * m_object;
};
Another idea may be to have some parent AbstractType that I would be using in the vector, but I'm not sure how that would help with the templated type problem.
Different instantiations of a class template are completely unrelated types, so you cannot have a container that directly stores them.
You have a few options:
Keep a collection of pointers to some base class that your class template inherits from:
class Base
{
virtual ~Base {}
virtual void someMethod() const = 0;
};
template <typename T>
class MyClass : public Base
{
void someMethod() const
{
// stuff
}
};
int main()
{
std::vector<std::unique_ptr<Base>> objs;
objs.push_back(std::make_unique<MyClass<int>>());
objs.push_back(std::make_unique<MyClass<std::string>>());
for (auto& i : objs) {
i->someMethod();
}
}
This is a fairly simple approach, but it incurs a bit of runtime overhead with dynamic allocation and RTTI. Note also that someMethod can't return T, since it's a method on a parent class that doesn't know what T is.
Use some sort of type-erased wrapper like boost::any (or the forthcoming std::any in C++17).
#include <any>
#include <string>
#include <vector>
template <typename T>
class MyClass {
public:
T someMethod() const {
// stuff
return {};
}
};
void someFunctionThatTakesInt(int i) {}
void someFunctionThatTakesString(std::string s) {}
int main() {
std::vector<std::any> objs;
objs.push_back(MyClass<int>());
objs.push_back(MyClass<std::string>());
for (const auto& i : objs) {
if (i.type() == typeid(MyClass<int>)) {
auto& mc = std::any_cast<const MyClass<int>&>(i);
someFunctionThatTakesInt(mc.someMethod());
} else if (i.type() == typeid(MyClass<std::string>)) {
auto& mc = std::any_cast<const MyClass<std::string>&>(i);
someFunctionThatTakesString(mc.someMethod());
}
}
}
This approach means that you can have someMethod return T, but makes it much harder to handle retrieving objects from the vector because you have to figure out what type they are before you can do anything with them (you're essentially rolling your own RTTI).
Don't.
Rethink why you need this in the first place. Maybe another approach could work better. Maybe something with callbacks or visitors. I don't know your objective here, so I can't really say what's appropriate.
Can you do a base class and have all other classes inherit from the base class.
And you can make a list that holds a list of base class elements.
Now this is more of a pseudo example, but I hope this way would solve your problem.
Example:
class Base:
{
}
class whatever:Base
{
}
class whatever2:Base
int main()
{
list<whatever> object1;
list<whatever2> object2;
list<list<Base>> mainObj;
mainObj.push_back(object1);
mainObj.push_back(object2);
}
Now if the problem is to just have different datatypes than abstract datatypes in some container. Can't you have a Singly Link List, and have your Node generic.
Example:
template<typenameT>
struct Node
{
T data;
Node* next;
}
class LinkList
{
//Your code:
}

Stack of class member functions but the class isn't known yet

I have something a little tricky to explain so I'll try my best. I have an InstructionScreen class that displays arrows & blocks of text that explain what each buttons does & etc. So in InstructionScreen I have a stack of member functions each of those functions will create some arrows & text to explain what a different button does.
The InstructionScreen will be subclassed into MenuInstructScreen, OptionsInstructScreen & etc. and in these classes I will create custom functions that will create arrows & text to explain their screens buttons.
The problem is declaring this stack in InstructionScreen because it will contain functions that are part of their subclass. I am thinking I can do this, but I use templates right?
So the problem in a nutshell is how do I declare a stack that will contain member functions of a class that doesn't exist yet?
The problem is a lot easier to understand & see if you look at this simple example:
typedef class InstructionScreen;
typedef class MenuInstructScreen;
template <typename FooClass>
typedef void (FooClass::*MemberFuncPtr)(); // will be typedef void (MenuInstructScreen::*MemberFuncPtr)();
class InstructionScreen
{
public:
InstructionScreen() {}
void runInstructions()
{
while ( !instructionStep.empty() )
{
(this->*instructionStep.top())();
instructionStep.pop();
}
}
protected:
stack <MemberFuncPtr> instructionStep;
};
class MenuInstructScreen : public InstructionScreen
{
public:
MenuInstructScreen()
{
// Set instruction schedule
instructionStep.push( &MenuInstructScreen::step2() );
instructionStep.push( &MenuInstructScreen::step1() );
}
void step1()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
void step2()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
private:
};
class OptionsInstructScreen : public InstructionScreen
{
public:
OptionsInstructScreen()
{
// Set instruction schedule
instructionStep.push( &OptionsInstructScreen::step2() );
instructionStep.push( &OptionsInstructScreen::step1() );
}
void step1()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
void step2()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
private:
};
C++ doesn't allow templated typedefs, but C++11 supports this via Template Aliases. If you don't have C++11 support in your compiler, you could achieve the same by using a functor such as Boost.Function.
typedef boost::function<void()> Func;
Since your typedef is for member functions that take no arguments, you could use the aboce to define a functor that returns void and accepts no arguments. Although it wouldn't be restricted to members of a specific class. You would push items onto your stack in derived classes using something like:
stack.push(boost::bind(&MenuInstructScreen::step2, this));
stack.push(boost::bind(&MenuInstructScreen::step1, this));
Your original example would now look something like this...
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <stack>
class InstructionScreen
{
public:
void runInstructions()
{
while (!instructionStep.empty())
{
boost::function<void()> func = instructionStep.top();
instructionStep.pop();
func();
}
}
protected:
std::stack<boost::function<void()> > instructionStep;
};
class MenuInstructScreen : public InstructionScreen
{
public:
MenuInstructScreen()
{
instructionStep.push(boost::bind(&MenuInstructScreen::step2, this));
instructionStep.push(boost::bind(&MenuInstructScreen::step1, this));
}
void step1()
{
//
}
void step2()
{
//
}
};
class OptionsInstructScreen : public InstructionScreen
{
public:
OptionsInstructScreen()
{
instructionStep.push(boost::bind(&OptionsInstructScreen::step2, this));
instructionStep.push(boost::bind(&OptionsInstructScreen::step1, this));
}
void step1()
{
//
}
void step2()
{
//
}
private:
};
int main() { }
There are no "template typedef"s in C++. In C++0x you can use template aliases, but support for that is limited at the moment.
Why not simply add a virtual function to your base class:
virtual void steps() { };
Then let each derived class implement it:
void steps() { step1(); step2(); }
Then you can store pointers-to-base-class in your stack and just call ->steps().

How do I make my Factory's Header not dependent on the templated objects it creates?

I have an abstract base class like so:
class AbstractBaseClass
{};
a templated concrete class that derives from it:
template<class T>
class ConcreteClass : public AbstractBaseClass
{
public:
ConcreteClass(T input) : data(input) {}
private:
T data;
};
AndI have a factory class that creates AbstractBaseClasses
class MyFactory
{
public:
boost::shared_ptr<AbstractBaseClass> CreateBlah();
boost::shared_ptr<AbstractBaseClass> CreateFoo();
template<class T>
boost::shared_ptr<AbstractBaseClass> Create(T input)
{
return boost::shared_ptr<AbstractBaseClass>(new ConcreteClass<T>(input));
}
};
The problem with this, is that now EVERYTHING that uses MyFactory has to include the entire implementation to ConcreteClass. Ideally, I want nothing but MyFactory to know about ConcreteClass.
Is there any way to architect this to achieve this goal? (Besides manually making a new Create function in MyFactory for every type I want instead of templating it).
you'll need to put the factory implementation into the implementation file (which you mentioned you'd like to avoid, but it is the lesser evil unless the interfaces are small, and/or your projects are small).
of course, there are a few other ways you could approach this, such as putting the implementation into base classes, and making derived bases factories, or using some other really weird template syntax to reduce instantiations in dependent translations. this really comes down to convenience and scale for your project. if you are working on one or more large projects, then full abstraction wrt instantiation will serve your needs best in the long run (assuming you need dynamic polymorphism and memory).
you may also try other approaches (such as overloading) to reduce errors by using type-safety.
the short answer is that you'll really need to abstract the interfaces/instantiation into one or multiple implementation files to remove header dependencies - very common idiom, and many ways to tackle it. you can over course further divide and use polymorphism for your factories as well.
you may also use template forward declarations to minimize the sets to the compilation unit. provided:
/** in MyIntermediateFactory.hpp */
class MyIntermediateFactory {
public:
static template<class T> boost::shared_ptr<T> Create(float);
};
/** in Concrete.hpp */
template<Concrete>
boost::shared_ptr<T> MyIntermediateFactory::Create<Concrete>(float arg) {
/* … */
}
using this you can select portions of programs/interfaces which you need in the library, then wrap it all up in a real Factory (for the build at hand). the linker/instantiation should fail along the way if you actually attempt to request a creation which is not visible.
there a lot of options, really - you need to figure out how big your scale is in order to determine what to abstract (or not). instantiation requires interface, to remove header dependencies, you'll have to abstract the instantiation someplace.
My approach to the same problem in the past was the creation of a set of concrete factories (one per type) that get registered in the global factory (for illustration purposes, indexing by object name):
class AbstractBaseClass;
class ConcreteFactory
{
public:
AbstractBaseClass * create();
};
class AbstractFactory
{
public:
void registerFactory( std::string const & name, std::shared_ptr<ConcreteFactory> const & f )
{
factory[ name ] = f; // check for collisions, complain if so ...
}
AbstractBaseClass * create( std::string const & name )
{
return factory[name]->create(); // check for existence before dereferencing...
}
private:
std::map<std::string, std::shared_ptr<ConcreteFactory> > factory;
};
I used this in a piece of code that was heavily templated to reduce compilation time. Each concrete factory and the class that it creates need only be in a single translation unit that registers the concrete factory. The rest of the code only need to use the common interface to AbstractBaseClass.
I realize I am answering this five years later. Maybe the language has grown a tad since then. I'd like to offer something that seems right, if I understand the question properly, if for no other point than to help others who might find this question and wonder what they could do.
factory.hpp
#include "base.hpp"
namespace tvr
{
namespace test
{
class factory
{
public:
typedef base::ptr Ptr;
enum eSpecial
{
eDerived
};
template<typename Type>
Ptr create()
{
Ptr result;
result.reset(new Type());
return result;
}
template<typename Type, typename DataType>
Ptr create(const DataType& data)
{
Ptr result;
result.reset(new Type(data));
return result;
}
template<typename Type, typename DataType>
Ptr create(const DataType& data, eSpecial tag)
{
Ptr result;
result.reset(new Type());
static_cast<Type*>(result.get())->set_item(data);
return result;
}
};
}
}
base.hpp
#include <memory>
namespace tvr
{
namespace test
{
class base
{
public:
typedef std::shared_ptr<base> ptr;
public:
base() {}
virtual ~base() {}
virtual void do_something() = 0;
};
}
}
some_class.hpp
#include <ostream>
namespace tvr
{
namespace test
{
struct some_class
{
};
}
}
std::ostream& operator<<(std::ostream& out, const tvr::test::some_class& item)
{
out << "This is just some class.";
return out;
}
template_derived.hpp
#include <iostream>
#include "base.hpp"
namespace tvr
{
namespace test
{
template<typename Type>
class template_derived : public base
{
public:
template_derived(){}
virtual ~template_derived(){}
virtual void do_something()
{
std::cout << "Doing something, like printing _item as \"" << _item << "\"." << std::endl;
}
void set_item(const Type data)
{
_item = data;
}
private:
Type _item;
};
}
}
and, finally, main.cpp
#include <vector>
#include "base.hpp"
#include "factory.hpp"
namespace tvr
{
namespace test
{
typedef std::vector<tvr::test::base::ptr> ptr_collection;
struct iterate_collection
{
void operator()(const ptr_collection& col)
{
for (ptr_collection::const_iterator iter = col.begin();
iter != col.end();
++iter)
{
iter->get()->do_something();
}
}
};
}
}
#include "template_derived.hpp"
#include "some_class.hpp"
namespace tvr
{
namespace test
{
inline int test()
{
ptr_collection items;
tvr::test::factory Factory;
typedef template_derived<unsigned int> UIntConcrete;
typedef template_derived<double> DoubleConcrete;
typedef template_derived<std::string> StringConcrete;
typedef template_derived<some_class> SomeClassConcrete;
items.push_back(Factory.create<SomeClassConcrete>(some_class(), tvr::test::factory::eDerived));
for (unsigned int i = 5; i < 7; ++i)
{
items.push_back(Factory.create<UIntConcrete>(i, tvr::test::factory::eDerived));
}
items.push_back(Factory.create<DoubleConcrete>(4.5, tvr::test::factory::eDerived));
items.push_back(Factory.create<StringConcrete>(std::string("Hi there!"), tvr::test::factory::eDerived));
iterate_collection DoThem;
DoThem(items);
return 0;
}
}
}
int main(int argc, const char* argv[])
{
tvr::test::test();
}
output
Doing something, like printing _item as "This is just some class.".
Doing something, like printing _item as "5".
Doing something, like printing _item as "6".
Doing something, like printing _item as "4.5".
Doing something, like printing _item as "Hi there!".
This uses a combination of templates, function overloading, and tagging through enums to help create a flexible factory class that doesn't require knowing much about the individual classes it instantiates, to include templated concrete classes as the OP asked about.
The 'eDerived' tag (in the form of an enum) tells the compiler to use the version of the factory's create function that takes a class like the template_derived class, which has a function that allows me to assign data to one of its members. As you can tell from the way I ordered the headers in main.cpp, the factory doesn't know anything about template_derived. Neither does the function calling the base class's virtual function (do_something). I think this is what the OP wanted, but without having to add a various create functions within every class that this factory might generate.
I also showed how one doesn't have to explicitly create functions for each class the factory should create. The factory's overloaded create functions can create anything derived from the base class that matches the appropriate signature.
I didn't do an extensive performance analysis on this code, but I did enough to see that the majority of the work happens in the streaming operator. This compiles in about 1 second on my 3.30Ghz quad core machine. You might need to experiment with more robust code to see how badly it might bog down the compiler, if much at all.
I've tested this code in VC++ 2015, although it probably works in other compilers pretty easily. If you want to copy this, you'll need to add your own guard headers. In any event, I hope this is useful.
You could use explicit template instanciation. Trying to call the factory method with a template parameter not explicit instanciated will give you a linker error. Note the explicit template instanciation in MyFactory.cpp
template AbstractBaseClass* MyFactory::Create(int input);
All put together looks like this (I removed shared_ptr for the sake of simplicity):
Main.cpp:
#include "AbstractBaseClass.h"
#include "MyFactory.h"
//we do not need to know nothing about concreteclass (neither MyFactory.h includes it)
int main()
{
MyFactory f;
AbstractBaseClass* ab = f.Create(10);
ab = f.Create(10.0f);
return 0;
}
MyFactory.h:
#include "AbstractBaseClass.h"
class MyFactory
{
public:
template<class T>
AbstractBaseClass* Create(T input);
};
MyFactory.cpp:
#include "MyFactory.h"
#include "ConcreteClass.h"
template<class T>
AbstractBaseClass* MyFactory::Create(T input) {
return new ConcreteClass<T>(input);
}
//explicit template instanciation
template AbstractBaseClass* MyFactory::Create(int input);
//you could use as well specialisation for certain types
template<>
AbstractBaseClass* MyFactory::Create(float input) {
return new ConcreteClass<float>(input);
}
AbstractBaseClass.h:
class AbstractBaseClass{};
ConcreteClass.h:
#include "AbstractBaseClass.h"
template<class T>
class ConcreteClass : public AbstractBaseClass
{
public:
ConcreteClass(T input) : data(input) {}
private:
T data;
};
You're looking for the "PIMPL" idiom. There's a good explanation at Herb Sutter's GOTW site
It can't be done because ConcreteClass is a template, that means you need the complete implementation available at compile time. Same reason why you can't precompile templates and have to write them all in header files instead.

how to implement common functor for several classes in c++

suppose you have two (or more) classes with private member vectors:
class A {
private:
std::vector<X> priv_vec;
public:
//more stuff
}
class B {
private:
std::vector<Y> priv_vec;
public:
//more stuff
}
and you have a functor-class which has a state and works on a generic vector (does sorting or counts elements or something like that). The state of the functor is initialized by the first vector the functor is working on. If the functor is applied to another vector later, it will change its behavior depending on the state (sorts in the same way or trims the second vector after as many elements as the first one, etc)
What is the best way to implement such a functor (desgin-pattern or functional interface?) without exposing the private vectors to the other classes or the user of the classes?
for example:
The user would like to initialize this functor with an object of class A and then use this initialized functor for one or more objects of class B. The user isn't able (and shouldn't be) to use the private vectors directly as function-arguments for the functor.
Hum, first, beware on states in functors.
Most STL implementation of the algorithms may copy your functors around, therefore you generally have to extract the state in an outer structure.
Now, for the application of functors, well it is simple: have your classes declare a template member function!
class A
{
public:
template <class Functor>
Functor Apply(Functor f);
private:
};
class B
{
public:
template <class Functor>
Functor Apply(Functor f);
};
// Usage
MyFunctor f;
A a;
B b;
b.Apply(a.Apply(f));
As for the functor, if you need state:
// Alternative 1
class FunctorState {};
class Functor
{
public:
Functor(FunctorState& state): m_state(state) {}
// some operator()(...)
private:
FunctorState& m_state;
};
// Alternative 2
class Functor
{
struct FunctorState {};
public:
Functor(): m_state(new FunctorState) {}
// some operator()(...)
private:
boost::shared_ptr<FunctorState> m_state;
};
This way, copies of the Functor all points to the same FunctorState instance. Just choose depending if you wish to actually access the state from outside the class or not.
Looks like a problem of importing policies from an object of class A and applying them to objects of class B, the only difference being, all of this is done at runtime (as opposed to typical policy-based design). This begs the question, are these policies proprietary to class A or can we isolate them and pass them around as required? That ought to simplify the deisgn.
A solution based on templates.
#include <iostream>
#include <string>
#include <vector>
// Wraps up a vector of type T and exposes a
// simple interface to access it.
template <class T>
class A
{
public:
A(const std::vector<T>& v) : priv_vec(v) { }
virtual size_t count() const { return priv_vec.size(); }
virtual T operator[](size_t index) const { return priv_vec[index]; }
private:
std::vector<T> priv_vec;
};
// A sample functor with state.
// The state is the size and current index of the vector object.
class Functor
{
public:
Functor() : _size(0), _index(0) { }
// Prints the element at the current index.
// If the index exceeds size, it is reset to 0.
template <class T>
void operator()(const A<T>& b)
{
if (_size == 0) _size = b.count();
if (_index >= _size) _index = 0;
std::cout << b[_index++] << '\n';
}
private:
size_t _size;
size_t _index;
};
int
main()
{
// Some tests.
std::vector<int> int_vec;
int_vec.push_back(1);
int_vec.push_back(2);
int_vec.push_back(3);
A<int> a(int_vec);
std::vector<std::string> str_vec;
str_vec.push_back("aaaa");
str_vec.push_back("bbbb");
str_vec.push_back("cccc");
A<std::string> b(str_vec);
Functor f;
f(a); // 1
f(b); // bbbb
f(a); // 3
f(a); // 1
f(a); // 2
f(b); // cccc
return 0;
}