I'm trying to initialize a private member array of a class without using the STL (because it is not supported on the Arduino microcontroller platform I'm using). This means no std::array or std::initializer_list etc.
The following compiles correctly using gcc 5.4.0 and avr-gcc 4.9.2, but that seems to be a bug. Clang throws an error saying error: array initializer must be an initializer list (as expected).
Code
#include <iostream>
#define PRINTFN() std::cout << __PRETTY_FUNCTION__ << std::endl
class Object {
public:
Object(int number) : number(number) { PRINTFN(); }
Object(const Object &o) : number(o.number) { PRINTFN(); }
void print() { std::cout << "The number is " << number << std::endl; }
private:
const int number;
};
template <size_t N>
class ManyObjects {
public:
ManyObjects(const Object(&objects)[N]) : objects(objects) {}
void print() {
for (Object &object : objects)
object.print();
}
private:
Object objects[N];
};
int main() {
ManyObjects<3> many = {{1, 2, 3}};
many.print();
}
Output
Object::Object(int)
Object::Object(int)
Object::Object(int)
Object::Object(const Object&)
Object::Object(const Object&)
Object::Object(const Object&)
The number is 1
The number is 2
The number is 3
What is the proper way to initialize objects? Or is it just not possible with the given constraints?
You can use variadic templates:
In ManyObjects class:
template <typename... _Args>
ManyObjects(_Args&&... arguments) :
objects { arguments... }
{
}
More here
Yes variadic templates work but it is a bit tricky :
template <size_t N>
class ManyObjects {
public:
template<typename T, typename ...Args>
ManyObjects(const T& x, Args&&... args) : objects{x, args...}{}
private:
Object objects[N];
};
int main() {
ManyObjects<3> many{1, 2, 3};
ManyObjects<3> copymany{many};
copymany.print();
}
For any fixed N it can be interpreted as :
template <size_t N=3>
class ManyObjects {
public:
ManyObjects(int x, int y, int z) : objects{x, y, z}{}
...
};
What is at play here :
Object cannot be default initialized due to the definition of the constructor Object(int)
Object assignment operator is implicitly deleted because number is const
Thus any array Object arr[N] must be explicitly initialized using an aggregate initialization.
The only way I think of is to perform extended initialization via the variadic templates.
To prevent matching the copy constructor you can specify the first argument outside the parameter pack. You loose the construction of size 0, which can be enabled with a template specialization.
ManyObjects<0> noneof;
noneof.print();
I ended up following the advice of VTT, and creating my own array wrapper.
I'd love to hear some feedback if there are things that I have to look out for, or possible bugs, etc.
#include <iostream>
class Object {
public:
Object(int number) : number{number} {}
void print() { std::cout << "The number is " << number << std::endl; }
private:
const int number;
};
// -------------------------------------------------------------------------- //
template <class T, size_t N> class ArrayWrapper {
public:
T &operator[](size_t index) { return data[index]; }
const T &operator[](size_t index) const { return data[index]; }
T *begin() { return &data[0]; }
const T *begin() const { return &data[0]; }
T *end() { return &data[N]; }
const T *end() const { return &data[N]; }
T data[N];
};
// -------------------------------------------------------------------------- //
template <size_t N> class ManyObjects {
public:
ManyObjects(const ArrayWrapper<Object, N> &objects, const char *name)
: objects{objects}, name{name} {}
void print() {
std::cout << name << std::endl;
for (auto &object : objects)
object.print();
}
private:
ArrayWrapper<Object, N> objects;
const char *name;
};
// -------------------------------------------------------------------------- //
int main() {
ManyObjects<3> many = {{1, 2, 3}, "Many"};
many.print();
}
Related
I've got this class, called "Bundle", which acts as a transfer object between my business logic. By having two maps, one for const and one for non const values, I am able to preserve const-ness of data.
#pragma once
#include <lang/System.h>
#include <unordered_map>
class Bundle final : public Object {
private:
std::unordered_map<int, void *> nonConstMap;
std::unordered_map<int, const void *> constMap;
public:
CLASS_NAME("util.Bundle")
template <typename T, ENABLE_IF(IS_CONST(T))>
void setData(const int& key, T& value) {
constMap.emplace(key, &value);
}
template <typename T, ENABLE_IF(!IS_CONST(T))>
void setData(const int& key, T& value) {
nonConstMap.emplace(key, &value);
}
template <typename T,ENABLE_IF(!IS_CONST(T))>
T* getData(const int& key) {
return nonConstMap.count(key) > 0 ? static_cast<T*>(nonConstMap.at(key)) : null;
}
template <typename T, ENABLE_IF(IS_CONST(T))>
const T* getData(const int& key) const {
return constMap.count(key) > 0 ? static_cast<const T*>(constMap.at(key)) : null;
}
};
Which works in this way:
class Main : public CppApplication {
public:
CLASS_NAME("src.Main");
virtual int main(const std::vector<String>& arguments) override {
using StringReference = std::reference_wrapper<String>;
Bundle myBundle;
int intValue = 1;
String stringValue= "2";
String otherStringValue = "3";
std::vector<StringReference> vectorValue = { otherStringValue };
myBundle.setData<int>(1, intValue);
myBundle.setData<String>(2, stringValue);
myBundle.setData<std::vector<std::reference_wrapper<String>>>(3, vectorValue);
std::cout << *myBundle.getData<int>(1) << std::endl;
std::cout << *myBundle.getData<String>(2) << std::endl;
std:: cout << (*myBundle.getData<std::vector<StringReference>>(3))[0].get() << std::endl;
return 0;
}
};
SET_ENTRY_POINT(new Main());
It may happen in the future that one can invoke the "getData" method using a wrong template parameter type (i.e getData<int> instead of getData<String>). How can i trigger a compilation error when this happens?
Thanks
Assume I have a base class like this:
template<typename T>
class Base {
public:
Base& operator()(const T& value) {
this->value = value;
return *this;
}
T value;
};
Now I want to inherit from this class to create type-specific classes
class InheritedFloat : public Base<float> {} inheritedFloat;
Now here I try to catch this inheritance in a functon:
void function(const InheritedFloat& inherited) {
std::cout << inherited.value << '\n';
}
Calling this function like this works fine, of course:
int main() {
function(inheritedFloat); //(inheritedFloat is a global instance)
return 0;
}
But when I try to call it with the operator()(const float& value){...} member function, function(const InheritedFloat& inherited){...} doesn't see it as a InheritedFloat-Type but instead as a Base<float>-Type:
int main() {
function(inheritedFloat(10.f)); //error
return 0;
}
Error:
Error C2664 'void function(const InheritedFloat &)': cannot convert argument 1 from 'Base<float>' to 'const InheritedFloat &'
So how can I make operator()(const T& value){...} return InheritedFloat& instead of Base<float>&?
To clearify further, this is just a simplified example (of course). I have dozens of inheritance cases. So I can't just template-specify function()
template<typename T>
void function(const Base<T>& inherited) {
std::cout << inherited.value << '\n';
}
because each inheritance needs to be treated differently. Types will overlap, so there will be multiple Base<std::size_t> cases, for example.
The whole code:
#include <iostream>
template<typename T>
class Base {
public:
Base& operator()(const T& value) {
this->value = value;
return *this;
}
T value;
};
class InheritedFloat : public Base<float> {} inheritedFloat;
void function(const InheritedFloat& inherited) {
std::cout << inherited.value << '\n';
}
int main() {
function(inheritedFloat(10.f));
return 0;
}
Thanks for reading, I appreciate any help!
You can utilize CRTP here. By supplying extra template parameter you can make base class function return a reference to a derived class:
#include <iostream>
template<typename Derived, typename T>
class Base {
public:
Derived & operator()(const T& value) {
this->value = value;
return *static_cast<Derived *>(this);
}
T value;
};
class InheritedFloat : public Base<InheritedFloat, float> {} inheritedFloat;
void function(const InheritedFloat& inherited) {
std::cout << inherited.value << '\n';
}
int main() {
function(inheritedFloat(10.f));
return 0;
}
online compiler
If I have:
Class SomeClass{
private:
int a;
char* name;
public:
SomeClass(int a = 0, char* n = "---"){
...
}
};
Class OtherClass{
private:
SomeClass anArray[100];
int counter;
...
public:
...
};
How do I initialize the array of type SomeClass? As far as I know, when you have a private member that belongs to a user defined class, to initialize it you should include it in the constructor
OtherClass(...):SomeClass(...){
...
}
However, the contents of the array are left for the user to enter, so they are much too unpredictable, and manually entering default values for each field is obviously out of the question.
Given that your SomeClass has a default constructor, you don't need to anything: the default constructor will be call for each if the elements. You want to mention it explicitly can use
OtherClass::OtherClass()
: anArray() {
}
If you want to initialize the sequence of elements with an explicit constructor call with typing it out, you can use a delegating constructor taking a suitably size std::index_sequence<...> and use aggregate initialization of the elements. Here is a complete example of how that would look like:
#include <iterator>
#include <algorithm>
#include <iostream>
struct S {
int value;
S(int value): value(value) {}
};
std::ostream& operator<< (std::ostream& out, S const& s) {
return out << s.value;
}
template <typename S, typename T, std::size_t Size>
constexpr std::size_t static_size(T (S::*)[Size]) {
return Size;
}
class T {
S array[100];
template <std::size_t... I>
T(std::index_sequence<I...>): array{ S(I)... } {}
public:
T(): T(std::make_index_sequence<static_size(&T::array)>()) {}
S const* begin() const { return std::begin(array); }
S const* end() const { return std::end(array); }
};
int main()
{
T t;
std::copy(t.begin(), t.end(), std::ostream_iterator<S>(std::cout, " "));
}
I've got this Map in my Entity-Component-System:
std::map<u_int32_t, std::vector<std::shared_ptr<Component>>> _componentMap;
The u_int32_t is the key to a vector of components. There can be multiple instances of the same component. (That's why there's a vector).
Now I would like to have a templated getter-function that returns a Vector of an inherited type:
template<class T> inline const std::vector<std::shared_ptr<T>> & getVector() const
{
u_int32_t key = getKey<T>();
return static_cast<std::vector<std::shared_ptr<T>>>(_componentMap.count(key) ? _componentMap.at(key) : _emptyComponentVec);
}
I know that this doesn't work, since std::vectors of different types are completely unrelated and I cannot cast between them. I would also like to avoid allocating a new vector every time this function is called.
But how I can I get the desired behaviour? When the the components are added I can create an std::vector of the desired derived type.
The question could also be: How can I have an std::map containing different types of std::vector?
For any solutions I can not link against boost, though if absolutely needed, I could integrate single headers of boost.
template<class It>
struct range_view {
It b, e;
It begin() const { return b; }
It end() const { return e; }
using reference = decltype(*std::declval<It const&>());
reference operator[](std::size_t n) const
{
return b[n];
}
bool empty() const { return begin()==end(); }
std::size_t size() const { return end()-begin(); }
reference front() const {
return *begin();
}
reference back() const {
return *std::prev(end());
}
template<class O>
range_view( O&& o ):
b(std::begin(o)), e(std::end(o))
{}
};
this is a quick range view. It can be improved.
Now all you need to do is write a pseudo-random-access iterator that converts its arguments. So it takes a random access iterator over a type T, then does some operation F to return a type U. It forwards all other operations.
The map then stores std::vector<std::shared_ptr<Base>>. The gettor returns a range_view< converting_iterator<spBase2spDerived> >.
Here is a crude implementation of a solution I have in mind for this problem. Of course, there are many rooms to refine the code, but hopefully it conveys my idea.
#include <iostream>
#include <map>
#include <vector>
#include <memory>
using namespace std;
class Base {
public:
virtual void f() const = 0;
};
class A : public Base {
public:
static const int type = 0;
explicit A(int a) : a_(a) {}
void f() const { cout << "calling A::f" << endl;}
int a_;
};
class B : public Base {
public:
static const int type = 1;
explicit B(int a) : a_(a) {}
void f() const { cout << "calling B::f" << endl;}
int a_;
};
class MapWrapper {
public:
template<class T>
void append(int a, vector<T> const& vec) {
types_[a] = T::type;
my_map_[a] = make_shared<vector<T>>(vec);
}
template<class T>
vector<T> const& get(int a) const {
return *static_pointer_cast<vector<T>>( my_map_.at(a) );
}
map<int, shared_ptr<void>> const& get_my_map() const {
return my_map_;
}
vector<shared_ptr<Base>> get_base(int a) const {
vector<shared_ptr<Base>> ret;
switch(types_.at(a)) {
case 0: {
auto const vec = get<A>(a);
for(auto v : vec)
ret.push_back(make_shared<A>(v));
break;
}
case 1: {
auto const vec = get<B>(a);
for(auto v : vec)
ret.push_back(make_shared<B>(v));
break;
}
}
return ret;
}
map<int, shared_ptr<void>> my_map_;
map<int, int> types_;
};
int main() {
MapWrapper map_wrapper;
map_wrapper.append(10, vector<A>{A(2), A(4)});
map_wrapper.append(20, vector<B>{B(5), B(7), B(9)});
for(auto const& w : map_wrapper.get_my_map())
for(auto v : map_wrapper.get_base(w.first))
v->f();
for(auto const& x: map_wrapper.get<A>(10))
cout << x.a_ << " ";
cout << endl;
for(auto const& x: map_wrapper.get<B>(20))
cout << x.a_ << " ";
return 0;
}
The solution was to use reinterpret_cast:
template<class T> inline std::vector<std::shared_ptr<T>> * getVector() const
{
auto key = getKey<T>();
return reinterpret_cast<std::vector<std::shared_ptr<T>> *>( (_componentMap.count(key) ? _componentMap.at(key).get() : const_cast<std::vector<std::shared_ptr<Component>> *>(&_emptyComponentSharedPtrVec)) );
}
It's not very pretty but it does work fine and it fulfills all requirements.
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);
}