I have the goal to make a base class, and a CRTP subbase class containing a static vector that will hold different values for each Derived class. However each object from the derived class must be able to see only one vector for the entire class. Moreover, I need to manipulate this vector through a common interface, this is why I am setting up a Base class.
Base class and subbase
class Seq {
public:
virtual unsigned long int elem(int i) = 0;
virtual void print(ostream& os) =0; // print out to a ostream
virtual int length() const =0;// return size of vector
virtual ~Seq() {}
protected:
virtual void gen_elems(int i) = 0; //generates elements
};
template<class T>
class subSeq: public Seq {
public:
unsigned long int elem(int i);
void print(ostream& os);
int length() const {return (int)memory.size();}
virtual ~subSeq() {}
protected:
static vector<long int> memory;
virtual void gen_elems(int i) = 0;
};
template<class T>
void subSeq<T>::print(ostream& os) {
if((int)memory.size() != 0) {
cout << "Stored numbers: ";
for(int i=0; i<(int)memory.size(); i++) {
os << memory[i] << " ";
}
cout << "\n";
} else {
cout << "Empty class!!\n";
}
}
template<class T>
unsigned long int subSeq<T>::elem(int i) {
if( i>=(int)memory.size() ) gen_elems(i);
return memory[i];
}
One of my derived classes:
class Fibonnacci: public subSeq<Fibonnacci> {
public:
Fibonnacci(int=0);
~Fibonnacci() {}
protected:
void gen_elems(int i); // Gera os elementos da série até o iésimo elemento (protected)
};
and its implementation:
Fibonnacci::Fibonnacci(int param) { if(param) gen_elems(param); }
void Fibonnacci::gen_elems(int param) {
for(int i=(int)memory.size(); i<param; i++) {
if(i>1) memory.push_back((long int)memory[i-1]+memory[i-2]);
else memory.push_back(1);
}
}
the problem occurs around this line
if(i>1) memory.push_back((long int)memory[i-1]+memory[i-2]);
compiler yells at me for
undefined reference to `subSeq<Fibonnacci>::memory'
this has been going on for hours, and since I am new to the concept CRTP, I see I don't understand it well and need help of people more capable than me.
Could someone enlighten me to what the problem is?
The member
template <>
vector<long int> subSeq<Fibonnacci>::memory;
Should be defined somewhere. To achieve your desired result, you should do this explicitly yourself in only a single translation unit (cpp file).
Or alternatively;
template <class T>
vector<long int> subSeq<T>::memory = {};
As some compilers do support common data folding (e.g COMDAT in msvc) which may help if you wish to use implicit instantiations, note this answer for more detail on common symbols.
Related
I have some class that should be populated with values,
but I don't know the type of values.
To clarify, each vector in a class instance is populated with the same value types,
But one instance of SomeClass can have vector<int> and another vector<string> and so on.
How can I declare the vector as template, but not template the class itself?
template<typename T>
struct tvector {
typedef std::vector< std::vector<T> > type;
};
class SomeClass {
public:
int _someField;
tvector<T> _fieldValues; // this line fails to compile
};
Thanks in advance
There are a few different ways to shear this beast. It mostly depends on how you want to access this vector and how you determine its exact type at runtime.
std::variant
A variant can store a set of predetermined types. It's effective but also cumbersome if you have many different types because you have to funnel every access through some type checking.
class SomeClass {
public:
using variant_type = std::variant<
std::vector<int>, std::vector<double> >;
int _someField;
variant_type _fieldValues;
void print(std::ostream& stream) const
{
switch(_fieldValues.index()) {
case 0:
for(int i: std::get<0>(_fieldValues))
stream << i << ' ';
break;
case 1:
for(double i: std::get<1>(_fieldValues))
stream << i << ' ';
break;
default: break;
}
}
};
std::any
Any can hold literally any type. Improves extendability but makes working with the values hard.
class SomeClass {
public:
int _someField;
std::any _fieldValues;
void print(std::ostream& stream) const
{
if(_fieldValues.type() == typeid(std::vector<int>))
for(int i: std::any_cast<std::vector<int>>(_fieldValues))
stream << i << ' ';
else if(_fieldValues.type() == typeid(std::vector<double>))
for(double i: std::any_cast<std::vector<double>>(_fieldValues))
stream << i << ' ';
else
throw std::runtime_error("Not implemented");
}
};
Subclassing
The most elegant way (IMHO) is to use a templated subclass. Something like this:
class SomeClass {
public:
int _someField;
virtual ~SomeClass() = default;
virtual void print(std::ostream& stream) const = 0;
};
template<class T>
SomeClassT: public SomeClass
{
std::vector<T> _fieldValues;
public:
virtual void print(std::ostream& stream) const
{
for(const T& i: _fieldValues)
stream << i << ' ';
}
};
Or if you don't want to expose that part, make it a private member.
class SomeClassHelper {
public:
virtual ~SomeClassHelper() = default;
virtual void print(std::ostream& stream) const = 0;
};
template<class T>
SomeClassHelperT: public SomeClassHelper
{
std::vector<T> _fieldValues;
public:
virtual void print(std::ostream& stream) const
{
for(const T& i: _fieldValues)
stream << i << ' ';
}
};
class SomeClass {
public:
int _someField;
private:
std::unique_ptr<SomeClassHelper> helper;
public:
void print(std::ostream& stream) const
{ return helper->print(stream); }
};
I have written a small piece of code where I am able to call setter and getter functions packed within a functoid using mem_fun templates.
I now would like to use this approach on top of a class hierarchy where every class might have getter and setter which can be registered as pair within a vector or array to be able to call the getter and setter if needed. GUIObject and GUICompositeObject are example classes out of the described class hierarchy.
The bound_mem_fun_t for the objects have unfortunately different types and thats the reason I don't know how to integrate them into an array/vector of pointers to the functors.
In c++11 I would use std::function. Is there a way to emulate this in c++98?
Because our compiler support only c++98 I cannot use the new features of c++11 or c++14. Also boost is not allowed.
#include <functional>
class GUIObject
{
int m_Alpha;
public:
void SetAlpha(int a) { m_Alpha = a;};
int GetAlpha() {return m_Alpha;};
};
class GUICompositeObject: public GUIObject
{
int m_NumOfChilds;
public:
void SetNumOfChilds(int NumOfChilds) { m_NumOfChilds = NumOfChilds;};
int GetNumOfChilds() {return m_NumOfChilds;};
};
template<typename T>
struct bound_mem_fun_t
{
bound_mem_fun_t(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o) :
m_GetFunc(GetFunc), m_SetFunc(SetFunc), obj(o) { } ;
int operator()() { return m_GetFunc(obj); } ;
void operator()(int i) { m_SetFunc(obj, i); } ;
std::mem_fun_t<int, T> m_GetFunc;
std::mem_fun1_t<void, T, int> m_SetFunc;
T* obj;
};
int main()
{
GUIObject kGUIObject;
GUICompositeObject kCompObj;
bound_mem_fun_t<GUIObject> GUIObjectFunc(std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject);
GUIObjectFunc(17);
int ii = GUIObjectFunc();
bound_mem_fun_t<GUICompositeObject> GUICompObjectFunc(std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj);
GUICompObjectFunc(17);
int iChilds = GUICompObjectFunc();
return 0;
}
Here is the complete solution after #filmors answer:
#include <functional>
#include <vector>
#include <iostream>
class GUIObject
{
int m_Alpha;
public:
void SetAlpha(int a) { m_Alpha = a;};
int GetAlpha() {return m_Alpha;};
};
class GUICompositeObject: public GUIObject
{
int m_NumOfChilds;
public:
void SetNumOfChilds(int NumOfChilds) { m_NumOfChilds = NumOfChilds;};
int GetNumOfChilds() {return m_NumOfChilds;};
};
struct bound_mem_fun_base
{
virtual int operator()() =0;
virtual void operator()(int) =0;
};
template<typename T>
struct bound_mem_fun_t : public bound_mem_fun_base
{
bound_mem_fun_t(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o) :
m_GetFunc(GetFunc), m_SetFunc(SetFunc), obj(o) { } ;
virtual int operator()() { return m_GetFunc(obj); } ;
virtual void operator()(int i) { m_SetFunc(obj, i); } ;
std::mem_fun_t<int, T> m_GetFunc;
std::mem_fun1_t<void, T, int> m_SetFunc;
T* obj;
};
template<typename T> bound_mem_fun_t<T>* make_setter(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o)
{
return new bound_mem_fun_t<T> (GetFunc, SetFunc, o);
}
int main()
{
GUIObject kGUIObject;
GUICompositeObject kCompObj;
std::vector<bound_mem_fun_base*> kBoundVector;
kBoundVector.push_back(new bound_mem_fun_t<GUIObject> (std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject));
kBoundVector.push_back(new bound_mem_fun_t<GUICompositeObject> (std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj));
kBoundVector.push_back(make_setter<GUIObject> (std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject));
kBoundVector.push_back(make_setter<GUICompositeObject> (std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj));
for (int i = 0; i < 4 ; i++)
{
(*kBoundVector[i])(i*10);
int res = (*kBoundVector[i])();
std::cout << "Getter result " << res << "\n";
}
return 0;
}
Unfortunately the make_setter function does not really shorten the creation of the functor. Any ideas will be welcome.
Just give your bound_mem_fun_t<T> a common base class and use dynamic dispatch to solve your problem:
struct bound_mem_fun_base {
virtual int operator()() = 0;
virtual void operator()(int) = 0;
};
template <typename T>
struct bound_mem_fun_t : bound_mem_fun_t ...
Then you can keep pointers to bound_mem_fun_base in your vector and call the elements as (*v[0])().
Also, TR1 does contain std::tr1::function, is that available?
First a remark on std::function from c++11: That will not solve your problem, because you need an already bounded function pointer. This pointer must be bound to your object. I believe what you need is an own implementation to std::bind.
I started only a very! small Binder class which is hopefully a starting point for your needs. If you need to have template parameter lists in older c++ versions, take a look for loki. http://loki-lib.sourceforge.net/
As a hint I can give you a short example of what i did:
class A
{
private:
int val;
public:
A(int i): val(i) {}
void Do(int i) { std::cout << "A " << val<< " " << i << std::endl; }
};
class B
{
private:
int val;
public:
B(int i): val(i){}
void Go(int i) { std::cout << "B " << val << " " << i << std::endl; }
};
class Base
{
public:
virtual void operator()(int i)=0;
};
template <typename T>
class Binder: public Base
{
void (T::*fnct)(int);
T* obj;
public:
Binder( void(T::*_fnct)(int), T*_obj):fnct(_fnct),obj(_obj){}
void operator()(int i)
{
(obj->*fnct)(i);
}
};
int main()
{
A a(100);
B b(200);
// c++11 usage for this example
//std::function<void(int)> af= std::bind( &A::Do, &a, std::placeholders::_1);
//af(1);
// hand crafted solution
Base* actions[2];
actions[0]= new Binder<A>( &A::Do, &a);
actions[1]= new Binder<B>( &B::Go, &b);
actions[0]->operator()(55);
actions[1]->operator()(77);
}
I've got a class D, that I want to have classes A,B,C inherit from. However, the functions that I want to declare as pure virtual are templated.
Unfortunately, in the words of visual studio:
member function templates cannot be virtual
Classes A,B,C have a member operator called in the exact same manner, though may return different values (double or unsigned int namely. But I'd be happy to get it to work with just double):
template<typename T>
double operator()(T&, unsigned int b){/*code*/};
How could I properly create a polymorphic collection of classes A,B,C (similar to a std::vector<D*> that would work if I didn't want member function templates) that does what I'm trying to do?
EDIT:
An example of what I'd like to be able to do:
std::default_random_engine rng((unsigned int) std::time(0));
std::vector<D*> v;
v.push_back(new A(0.3));
v.push_back(new B(1.0,3.2));
v.push_back(new C);
for(auto x : v){
for(auto y : x->operator()(rng,5){
std::cout << y << ',';
}
std::cout << std::endl;
}
I'm not entirely sure what you want to do, but if you move the template definition to the class instead of the method, everything is happy. Does that do what you want?
template<typename T>
class A
{
public :
virtual double operator() (T& t, unsigned int b) = 0;
};
template<typename T>
class B : public A<T>
{
public:
virtual double operator() (T& t, unsigned int b)
{
// code
}
};
EDIT:
Or, given that you don't want the template at the class level, what about moving the random calculation out of the polymorphic method, and then having a simple plymorphic method for the actual hard part. This assumes you only want to generate one random number, If you want more, you could always create a vector of random numbers, the size of which is determined in construction. Anyway the code below demonstrates what I am talking about:
class D
{
public :
template<typename T>
double operator() (T& t, unsigned int b)
{
double calc_rand = t();
return DoStuff(calc_rand, b);
}
protected :
virtual double DoStuff(double rnd_value, unsigned int b) = 0;
};
class A : public D
{
protected :
virtual double DoStuff(double rnd_value, unsigned int b)
{
return rnd_value * b;
}
};
int main(void)
{
std::random_device rd;
A a;
std::cout << a(rd, 5) << std::endl;
}
You'll most probably need to use delegates here. If all the classes have the same name and parameters, it's as easy as doing:
template <typename T>
class baseWrapper{
double method(T& a, unsigned int b) = 0;
};
template <typename T, typename myClass>
class wrapper: public baseWrapper<T>{
myClass &instance;
double method(T& a, unsigned int b){
return instance.method<T>(a,b);
};
wrapper(myClass &instance){this->instance = instance;};
};
And then you can create a collection of delegates:
std::vector<baseWrapper<int>*> vec;
A myObject1, B myObject2;
wrapper<int,A> wrapper1(myObject1);
wrapper<int,B> wrapper2(myObject2);
vec.push_back(&wrapper1);
vec.push_back(&wrapper2);
If the functions are named differently, you'll need to pass a function pointer as an additional parameter, or test it with SFINAE.
Perhaps you can implement a type erasure for the template parameter of the member functions. Going with your RNG example:
class RandUIntIfc {
public:
virtual ~RandUIntIfc() = 0;
virtual unsigned int min() const = 0;
virtual unsigned int max() const = 0;
virtual unsigned int operator()() = 0;
};
class RandUInt {
public:
template <typename RNG>
explicit RandUInt(RNG& rng);
unsigned int min() const;
unsigned int max() const;
unsigned int operator()();
private:
std::shared_ptr<RandUIntIfc> impl_;
template <typename RNG>
class Impl : public RandUIntIfc {
public:
explicit Impl(RNG& rng);
virtual unsigned int min() const;
virtual unsigned int max() const;
virtual unsigned int operator()();
private:
RNG& ref_;
};
};
I hope all the actual member definitions are obvious. That leaves just the change to D and code that uses it:
class D {
public:
virtual ~D() = 0;
virtual double operator()(RandUInt rng, unsigned int b) = 0;
};
std::default_random_engine rng((unsigned int) std::time(0));
RandUInt typeless_rng(rng);
std::vector<D*> v;
// ...
for(auto x : v){
for(auto y : x->operator()(typeless_rng,5){
std::cout << y << ',';
}
std::cout << std::endl;
}
You shouldn't use a template function but just pass delegate to the rng through the virtual function. So basically you could do this:
class D
{
virtual double operator()(std::function<int()>, int)=0;
};
And call it like this:
std::default_random_engine rng;
std::vector<D*> v;
...
for(auto x : v)
{
std::cout << x->operator(std::bind(rng), 5) << ',';
}
I would like some advice on how I can solve an interesting problem I have.
The problem is to have two storage containers, of which the user selects which one to use for the remainder of the program (edit: at runtime). The two containers are Vector and List and store an object type we are to define. These two containers can be accessed using any means you desire (pop/[i]/...) How would you go about solving this problem?
Below is my best (almost working) solution, but I would really like to see what solutions more skilled C++ professionals have. As previously stated, I am really interested if I am taking the right approach. I have more than typical free time this semester and I intend to use it to really improve my c++ abilities. Thanks for your feedback.
Version 1
To start, I have a boolean flag,
bool using_vector = true; // what storage container was selected?
Second comes my two containers,
list<Question> q_llist;
vector<Question> q_vec;
Third my implementations for accessing the containers,
(still haven't figured out how make get_question() work in a graceful way, and I am not fond of the current route I am taking at the moment)
const Question& get_question(){
Question q = (using_vector) ?
q_vec.back() : q_llist.back();
(using_vector) ?
q_vec.pop_back() : q_llist.pop_back();
return q;
}
int questions_size(){
return (using_vector) ?
q_vec.size() : q_llist.size();
}
void push_back_question(Question& q){
if(using_vector){
q_vec.push_back(q);
}else{
q_llist.push_back(q);
}
}
Version 2
Note: Please use the tag "#v2" when referencing.
I decided to attempt the polymorphism approach. How does this implementation look?
/**
* using polymorphism to implement a parent class "Container"
* depending on user selection, reference C_Vec or C_List
*/
class Container {
protected:
list<Question> qlist;
vector<Question> qvec;
public:
void push_back(Question& q){/** do nothing */}
void pop_back(){/** do nothing */}
int size(){/** do nothing */}
Question& back(){/** do nothing */}
};
class C_Vec: public Container{
public:
void push_back(Question& q){qvec.push_back(q);}
void pop_back(){qvec.pop_back();}
int size(){return qvec.size();}
Question& back(){return qvec.back();}
};
class C_List: public Container{
public:
void push_back(Question& q){qlist.push_back(q);}
void pop_back(){qlist.pop_back();}
int size(){return qlist.size();}
Question& back(){return qlist.back();}
};
int main(){
Container *store;
char user_in;
cout << "Before we begin please select a storage container:" << endl
<< "a) Linked List" << endl
<< "b) Vector" << endl << ':';
cin >> user_in;
if(tolower(user_in) == 'a'){
C_List l;
store = &l;
}else{
C_Vec v;
store = &v;
}
}
You have several options. If you need to decide at runtime which container to use, polymorphism (inheritance) might work well.
#include <vector>
#include <list>
#include <memory>
struct Question {};
// runtime
struct Question_container {
virtual const Question& get_question() = 0;
virtual int questions_size() = 0;
virtual void push_back(const Question&) = 0;
virtual ~Question_container() = default;
};
struct Vector_question_container : Question_container {
const Question& get_question() override { return qv.back(); }
int questions_size() override { return qv.size(); }
void push_back(const Question& q) override { qv.push_back(q); }
private:
std::vector<Question> qv;
};
struct List_question_container : Question_container {
const Question& get_question() override { return qv.back(); }
int questions_size() override { return qv.size(); }
void push_back(const Question& q) override { qv.push_back(q); }
private:
std::list<Question> qv;
};
int main()
{
// some how figure out which container to use
std::unique_ptr<Question_container> qc{new Vector_question_container()};
}
If you can make the choice at compile-time, you could make the underlying sequence a template (or even template template) argument.
// CompileTime
template<typename Sequence>
struct Question_container_c {
const Question& get_question() { return s.back(); }
int questions_size() { return s.size(); }
void push_back(const Question& q) { s.push_back(q); }
private:
Sequence s;
};
int main()
{
Question_container_c<std::list<Question>> qlc;
Question_container_c<std::vector<Question>> qvc;
return 0;
}
Although you could also just make your algorithm work on iterators and leave the choice of the container to the user. This might be hard for some methods such as your push_back, but it doesn't actually do anything else then the normal push_back already provided.
To complement #pmr's answer, if you want to do it in an idiomatic way, you can create an adapter interface:
class IContainer {
public:
virtual ~IContainer() {}
virtual void push_back(const Question & q) = 0;
virtual void pop_back() = 0;
virtual const Question & back() const = 0;
virtual unsigned int size() const = 0;
};
And a generic implementation:
template <class T>
class Container: public IContainer {
private:
T m_container;
public:
virtual void push_back(const Question & q) {
m_container.push_back(q);
}
virtual void pop_back() {
m_container.pop_back();
}
virtual const Question & back() const {
return m_container.back();
}
virtual unsigned int size() const {
return m_container.size();
}
};
So you can do this:
std::unique_ptr<IContainer> pctr;
if (choice) {
pctr.reset(new Container<std::vector<Question>>);
}
else {
pctr.reset(new Container<std::list<Question>>);
}
std::cout << pctr->size();
I suppose the best way for your approach is to use iterators instead. Iterators are invented as a container abstraction in mind (sure thing, you can't abstract by 100% due different behavior of containers but anyway you have a solution better than nothing).
I have implemented Decorator pattern in C++ as follows:
#include <iostream>
#include <string>
#include <deque>
using namespace std;
// Abstract Component
template <class T>
class IArray
{
public:
virtual void insert(const T&) = 0;
virtual ~IArray(){}
};
// Concrete Component
template <class T>
class Array : public IArray<T>
{
public:
virtual void insert(const T& elem)
{
m_array.push_back(elem);
}
private:
deque<T> m_array;
};
// Decorator 1
template <class T>
class PositiveArray : public IArray<T>
{
public:
PositiveArray(IArray<T>* component):m_component(component)
{
}
virtual void insert(const T& elem)
{
if (elem > 0)
{
m_component->insert(elem);
}
else
{
cerr << "You can't insert non-positive number." <<endl;
}
}
private:
IArray<T>* m_component;
};
// Decorator 2
template <class T>
class PrintArray : public IArray<T>
{
public:
PrintArray(IArray<T>* component):m_component(component)
{
}
virtual void insert(const T& elem)
{
m_component->insert(elem);
cout << "Element " << elem << " was inserted into the array." <<endl;
}
private:
IArray<T>* m_component;
};
// Client
int main()
{
typedef int MyType;
PositiveArray<MyType> arr(new PrintArray<MyType>(new Array<MyType>));
arr.insert(10);
arr.insert(-10);
int i;
cin>>i;
return 0;
}
Now I want to have for all arrays printArray function. Should I write it as a pure virtual function in IArray and copy the following implementation of that function in each child of IArray?
void printArray()
{
for (int i = 0; i < m_array.size(); ++i)
{
cout << "elem " <<i << " is " << m_array[i] <<endl;
}
}
Is there any solution that can avoid of copying?
I would implement for_each_element in either Array, and expose the interface in IArray. It has 2 overloads that take std::function< void(T const&) > and std::function< void(T) > (second one is optional). Now PrintArray is a one line lambda function.
In C++03 you can use boost::function, and PrintArray is more annoying to write. So here it is less tempting.
As another approach, expose const_iterators to the underlying data.
As an aside, deque performance is surprisingly poor. As yet, there is nothing in your code that would make me think you could not use a std::vector. If you guaranteed memory contiguity, you could even have your const_iterators be T const* and expose the interface directly from IArray (with the implementation in Array). for_each_element becomes a two-liner in C++11, and PrintArray even without C++11 or for_each_element is 2 lines, and either implemented inline in IArray or as a free function.
Oh, and I'd make PrintArray a free function rather than a member function. for_each_element may need to be a member function, but you should be able to PrintArray without access to private data, once you expose iterators and/or for_each_element.