Build initializer list for array by repeating n times - c++

I have a std:array something like this:
class MyClass {
private:
std::array<MyComplexType, 10> myArray;
}
In the constructor, I need to do the following:
MyClass::MyClass() : myArray({
MyComplexType(func(const_arg1, const_arg2, const_arg3).method(const_arg4)),
... repeated 8 more times...
MyComplexType(func(const_arg1, const_arg2, const_arg3).method(const_arg4))
})
Now, I want the 10 to be a compile-time constant that I can modify without having to copy&paste more (or less) of those initializers. They are all the same, I just need a "repeat n times". Everything up to and including C++17 is fair game.
I am 99.9% certain this should be doable with some template magic, but so far I came up with nothing that worked. Any ideas?
(And if it is impossible with templates, maybe with macros? Though I would hate having to go that direction...)

If you want to use a std::array you are going to need to build a helper function, namely a delegating constructor. Your default constructor will then call the delegate to actually initialize the member. That can look like
class MyClass {
public:
// default c'tor, create sequence of 10 integers
MyClass() : MyClass(std::make_index_sequence<10>{})
private:
// delegate, take a sequence and expand the initializer of myArray sizeof...(Is) times
template <std::size_t... Is>
MyClass(std::index_sequence<Is...>) :
myArray{ (Is, MyComplexType(func(const_arg1, const_arg2, const_arg3).method(const_arg4)))... } {}
std::array<MyComplexType, 10> myArray;
}
You can instead change myArray to be a vector instead and that would let you simplify the code to
class MyClass {
public:
MyClass() :
myData(MyComplexType(func(const_arg1, const_arg2, const_arg3).method(const_arg4)), 10) {}
private:
std::vector<MyComplexType> myData;
}

You could wrap the type into another struct/class which would provide an appropriate default constructor:
int f(int n)
{
return n;
}
struct S
{
S(int n) : n(n) { }
int n;
};
class MyClass
{
struct Wrapper
{
S s;
Wrapper() : s(f(7)) {}
};
std::array<Wrapper, 10> myArray;
};
You're now delegating the initialisation to the wrapper.
You might yet invest some work makeing the need of explicit indirection (myArray[i].s) obsolete, e.g. wrapping the array itself into another struct/class, too, providing the same interface as a std::array (as far as you need at least…) but with its iterators and index operators dereferencing to the complex type instead of to the wrapper (i.e. your iterator wraps around an array's iterator with S& operator*() { return i->s; } S* operator->() { return &i->s; } and further operators like increment just delegating to the wrapped iterator).

Related

The element without default constructor in the custom template container

I need to create a simple template container, which can store any object of any type and could be used everywhere. So, I did something like this:
template <typename Type>
class Container {
public:
Container() : arraySize(10) { valueWrappers = new Type[arraySize];}
Container(const Container& other) { /* --- */}
~Container() { /* --- */}
Container& operator=(const Container& other) { /* --- */}
/* some functions */
private:
int arraySize;
Type* valueWrappers;
};
Now I have the problem - when I'm trying to create my container using as template a class without default constructor, the compilation error appears:
class MyClass {
public:
MyClass(int value) :v(value) { }
private:
int v;
};
int main() {
Container<MyClass> cont;
return 0;
}
C2512 'MyClass': no appropriate default constructor available
The problem is that I need to initialize the array of "Type" values with something, but I don't no what I need to use. I can't use NULL because, in this case, Container will work only with pointers. So, can somebody give an advice, how am I able to do it? Or, maybe, there is another way to solve this task?
Based on your requirements, I think you're going to have to use placement new. Since you haven't provided all the relevant code, I'm going to do what I can.
First, you're going to have to allocate raw memory instead of using new directly.
Container() : arraySize(10) { valueWrappers = reinterpret_cast<Type*>(::operator new(sizeof(Type) * arraySize)); }
Now when you put something in your Container, you'll have to construct it in place, using something like the following:
new (valueWrappers + index) Type(arguments to type);
In your destructor, you'll need to explicitly call the destructors on any object that you used placement new for.
valueWrappers[index]->~Type();
Lastly, release the memory using ::operator delete.
::operator delete(valueWrappers);
Please bear in mind that this is a very quick and dirty answer, and this code can be hard to debug and maintain. You're going to have to keep track of what indexes in valueWrapper have been initialized and which haven't during cleanup. If possible, I highly recommend using something akin to std::vector, which handles all this complexity for you.
One option is to not allocate the array in the default constructor, but initialise valueWrappers to null instead. Another option is to not have a default constructor in your template. Third option is to keep your class as-is and simply document that the template is default constructible only if the type argument is default constructible.
You can use std::optional to defer initialization, which is guaranteed to handle object lifetime correctly. Letting a default constructed container have 10 elements is also a questionable choice — a (count) constructor may be preferable.
template <typename Type>
class Container {
using elem_t = std::optional<Type>;
std::size_t count{};
std::unique_ptr<elem_t[]> elems{};
public:
Container() = default;
Container(std::size_t cnt)
: count{cnt}
, elems{std::make_unique<elem_t[]>(cnt)}
{
}
// for example
template <typename... Args>
void construct_at(std::size_t pos, Args&&... args)
{
assert(pos < count);
assert(!elems[pos]);
elems[pos].emplace(std::forward<Args>(args)...);
}
// ...
};
Note that I used std::unique_ptr to simplify memory management; a pointer will also be OK, though apparently more error-prone. Now you can traverse the container and construct the elements:
class MyClass {
public:
MyClass(int value) :v(value) { }
private:
int v;
};
int main()
{
Container<MyClass> cont(10);
for (std::size_t i = 0; i < 10; ++i) {
cont.construct_at(i, /* argument */);
}
}

How to initialise explicit constructor in array initialiser list? [duplicate]

A library which I can't modify has a type akin to the following:
class A {
public:
A () : A(0) { }
explicit A (int const value) : value_(value) { }
A (A const &) = delete;
A (A &&) = delete;
A & operator= (A const &) = delete;
A & operator= (A &&) = delete;
private:
int value_;
}
Now, I have a class which requires a bunch of As as members. Due to other restrictions of the environment I'm working in all of these As must either be separate members or a member array (i.e. I can't use an std::vector to put them in or create pointers to them). I.e. my class boils down to this:
struct Foo {
A a[2];
}
Is there any way to initialize each member with a distinct initial value? I've been trying various forms of using braced-list initialization, but they all fail due to either A(int) being explicit or A not having a copy/move-constructor.
What doesn't work:
Foo () : A{ { 1 }, { 2 } } { }: won't call A(int) since it's explicit.
Foo () : A{ { A(1) }, { A(2) } } { }: can't copy- nor move-assign.
Edit: Updated info about member array requirement.
Edit 2: The library in question is SystemC. My example class A is a port (e.g. sc_core::sc_in).
The reason I can't use an array of pointers is because, as far as I know, Mentor Graphic's Questa can't really deal with them. It will simulate the model correctly, but won't allow inspection of the ports. I.e. it won't be able to plot the port's values over time in a wave window. I would be very happen to be proven wrong about this, because that would allow a trivial solution to my problem.
Edit 3: Apparently this is a big issue anymore in a newer version of Questa. I'm not sure what changed between seeing this problem and now, could be a change to the development environment as well (which is also out of my control). In any case, my Questa now automatically names ports after their variable name (unless explicitly renamed at construction), so all is well.
Just for the sake knowing how to I'd still like to see potential solutions to the original problem though.
struct Foo {
A a[2];
}
Is there any way to initialize each member with a distinct initial
value? I've been trying various forms of using braced-list
initialization, but they all fail due to either A(int) being
explicit or A not having a copy/move-constructor.
You may need to use placement-new to create an array of A in some raw storage array. You then create a std::initializer_list<ARGUMENT> of the ARGUMENTs needed to construct each A. Something like:
template<typename T, std::size_t Size, std::size_t Alignment = alignof(T)>
struct FixedArray{
std::aligned_storage_t<sizeof(T), Alignment> data[Size];
static constexpr std::size_t size = Size;
template<typename U>
FixedArray(std::initializer_list<U> ls){
assert(ls.size() <= Size && "Invalid Size"); int index = 0;
for(auto& x : ls)
new (&data[index++]) T(x);
}
FixedArray(const FixedArray&) = delete;
FixedArray(FixedArray&&) = delete;
A& operator[](std::size_t index){
auto ptr = reinterpret_cast<A*>(&data) + index;
return *std::launder(ptr); //Sort of a legal way to alias memory C++17
}
~FixedArray(){
for(std::size_t i = 0; i < size; i++)
this->operator[](i).~T();
}
};
Then declare Foo:
struct Foo {
FixedArray<A, 4> a;
};
To create Foo having A(546), A(99), A(-4), A(0):
int main() {
Foo f{{546, 99, -4, 0}};
return 0;
}
See a working Demo
After testing with GCC 6.3 at -O3 optimization levels, about exactly the same assembly is generated for using FixedArray vs plain raw arrays, See it on gcc.godbolt.com.
I am able to solve the problem as follows (also using SystemC, here my non-copyable, non-movable items are sc_modules):
class Object : sc_module {
Object(sc_module_name name){}
};
class Container : sc_module {
std::array<Object, 3> objects;
Container(sc_module_name name) :
objects{{{"object1"},{"object2"},{"object3"}}}
{}
};
The short answer - no. The longer answer - kind of, but its disgusting.
Take a look at this discussion.

Initialization of member array of non-copyable, non-movable, explicitly constructed types

A library which I can't modify has a type akin to the following:
class A {
public:
A () : A(0) { }
explicit A (int const value) : value_(value) { }
A (A const &) = delete;
A (A &&) = delete;
A & operator= (A const &) = delete;
A & operator= (A &&) = delete;
private:
int value_;
}
Now, I have a class which requires a bunch of As as members. Due to other restrictions of the environment I'm working in all of these As must either be separate members or a member array (i.e. I can't use an std::vector to put them in or create pointers to them). I.e. my class boils down to this:
struct Foo {
A a[2];
}
Is there any way to initialize each member with a distinct initial value? I've been trying various forms of using braced-list initialization, but they all fail due to either A(int) being explicit or A not having a copy/move-constructor.
What doesn't work:
Foo () : A{ { 1 }, { 2 } } { }: won't call A(int) since it's explicit.
Foo () : A{ { A(1) }, { A(2) } } { }: can't copy- nor move-assign.
Edit: Updated info about member array requirement.
Edit 2: The library in question is SystemC. My example class A is a port (e.g. sc_core::sc_in).
The reason I can't use an array of pointers is because, as far as I know, Mentor Graphic's Questa can't really deal with them. It will simulate the model correctly, but won't allow inspection of the ports. I.e. it won't be able to plot the port's values over time in a wave window. I would be very happen to be proven wrong about this, because that would allow a trivial solution to my problem.
Edit 3: Apparently this is a big issue anymore in a newer version of Questa. I'm not sure what changed between seeing this problem and now, could be a change to the development environment as well (which is also out of my control). In any case, my Questa now automatically names ports after their variable name (unless explicitly renamed at construction), so all is well.
Just for the sake knowing how to I'd still like to see potential solutions to the original problem though.
struct Foo {
A a[2];
}
Is there any way to initialize each member with a distinct initial
value? I've been trying various forms of using braced-list
initialization, but they all fail due to either A(int) being
explicit or A not having a copy/move-constructor.
You may need to use placement-new to create an array of A in some raw storage array. You then create a std::initializer_list<ARGUMENT> of the ARGUMENTs needed to construct each A. Something like:
template<typename T, std::size_t Size, std::size_t Alignment = alignof(T)>
struct FixedArray{
std::aligned_storage_t<sizeof(T), Alignment> data[Size];
static constexpr std::size_t size = Size;
template<typename U>
FixedArray(std::initializer_list<U> ls){
assert(ls.size() <= Size && "Invalid Size"); int index = 0;
for(auto& x : ls)
new (&data[index++]) T(x);
}
FixedArray(const FixedArray&) = delete;
FixedArray(FixedArray&&) = delete;
A& operator[](std::size_t index){
auto ptr = reinterpret_cast<A*>(&data) + index;
return *std::launder(ptr); //Sort of a legal way to alias memory C++17
}
~FixedArray(){
for(std::size_t i = 0; i < size; i++)
this->operator[](i).~T();
}
};
Then declare Foo:
struct Foo {
FixedArray<A, 4> a;
};
To create Foo having A(546), A(99), A(-4), A(0):
int main() {
Foo f{{546, 99, -4, 0}};
return 0;
}
See a working Demo
After testing with GCC 6.3 at -O3 optimization levels, about exactly the same assembly is generated for using FixedArray vs plain raw arrays, See it on gcc.godbolt.com.
I am able to solve the problem as follows (also using SystemC, here my non-copyable, non-movable items are sc_modules):
class Object : sc_module {
Object(sc_module_name name){}
};
class Container : sc_module {
std::array<Object, 3> objects;
Container(sc_module_name name) :
objects{{{"object1"},{"object2"},{"object3"}}}
{}
};
The short answer - no. The longer answer - kind of, but its disgusting.
Take a look at this discussion.

Recursive constructors in C++

I build a class for containing vectors with no default constructor. Specifically:
template<typename T>
struct MyVector
{
public:
int GetN(void)
{
return n;
}
MyVector(int n1)
{
n=n1;
ListElt = new T[n1];
}
~MyVector()
{
delete [] ListElt;
}
// some other irrelevant to the question code
private:
int n;
T *ListElt;
};
Now I want to build a class derived from it that contains one integer and a vector.
The code that works is the following:
struct EquivInfo {
public:
EquivInfo(int inpOrbit, MyVector<int> &inpMat)
{
iOrbit=inpOrbit;
eVect=new MyVector<int>(inpMat.getN());
// some code for copying the vector in place.
}
~EquivInfo()
{
delete eVect;
}
private:
int iOrbit;
MyVector<int> *eVect;
};
Is there a way to avoid the use of the pointer for the vector?
The problem is that if I remove the pointer then there is a call to a constructor of the kind MyVector(). I do not understand why. There should be a way to have a constructor for EquivInfo that calls a precise constructor for MyVector
I could add a constructor MyVector(), i.e. a default constructor that set the vector to something trivial. But precisely, I want to avoid such kind of constructors so that all vectors are well defined and the code is clean. The use of the pointer allows me to have a reasonable situation but I wonder if there is a clean way to avoid it.
Use member initializer list:
class EquivInfo {
public:
EquivInfo(int inpOrbit, MyVector<int> &inpMat)
: eVect(inpMat.getN())
, iOrbit(inpOrbit) {
// some code for copying the vector in place.
}
// ....
MyVector<int> eVect;
}

C++: automatic initialization

I find it sometimes annoying that I have to initialise all POD-types manually. E.g.
struct A {
int x;
/* other stuff ... */
A() : x(0) /*...*/ {}
A(/*..*/) : x(0) /*...*/ {}
};
I don't like this for several reasons:
I have to redo this in every constructor.
The initial value is at a different place than the variable declaration.
Sometimes the only reason I have to implement a constructor is because of this.
To overcome this, I try to use my own types instead. I.e. instead of using int x,y;, I use my own vector struct which also initialize automatically with 0. I also thought about just implementing some simple wrapper types, like:
template<typename T>
struct Num {
T num;
Num() : num(0) {}
operator T&() { return num; }
operator const T&() const { return num; }
T& operator=(T _n) { num = _n; return num; }
/* and all the other operators ... */
};
This basically solves this so far for all cases where I want to init with 0 (that are by far the most often cases for me).
Thanks to James McNellis for the hint: This can also be solved via the boost::value_initialized.
Now, not limited to POD-types:
But sometimes I want to initialise with something different and there are the troubles again because that Num template struct cannot easily be extended to allow that. Basically because I cannot pass floating point numbers (e.g. float) as a template parameter.
In Java, I would just do:
class A {
int x = 42;
/*...*/
public A() {}
public A(/*...*/) { /*...*/ }
public A(/*...*/) { /*...*/ }
/*...*/
}
I find it quite important that in such cases where you want to init a member variable always in the same way in all possible constructors, that you are able to write the init value directly next to the member variable, like in int x = 42;.
So the thing I was trying to solve is to do the same thing in C++.
To overcome the problem that I cannot pass the init-value via a template parameter, I hacked together an ugly macro:
#define _LINENAME_CAT( name, line ) name##line
#define _LINENAME( name, line ) _LINENAME_CAT( name, line )
/* HACK: use _LINENAME, workaround for a buggy MSVC compiler (http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=360628)*/
#define PIVar(T, def) \
struct _LINENAME(__predef, __LINE__) { \
typedef T type; \
template<typename _T> \
struct Data { \
_T var; \
Data() : var(def) {} \
}; \
Data<T> data; \
T& operator=(const T& d) { return data.var = d; } \
operator const T&() const { return data.var; } \
operator T&() { return data.var; } \
}
(For other compilers, I can just omit that _LINENAME name for the struct and just leave it unnamed. But MSVC doesn't like that.)
This now works more or less like I want it. Now it would look like:
struct A {
PIVar(int,42) x;
/*...*/
A() {}
A(/*...*/) { /*...*/ }
A(/*...*/) { /*...*/ }
/*...*/
};
While it does what I want (mostly), I still am not fully happy with it:
I don't like the name PIVar (which stands for PreInitVar) but I really couldn't come up with something better. At the same time, I want to have it short.
I don't like that macro hack.
How have you solved this? Any better solution?
There was an answer which was deleted again which said that C++0x allows basically the same syntax as in Java. Is that true? So then I would just have to wait for C++0x.
Please don't give any comments like:
"then just use Java instead" / "don't use C++ then" or
"if you need something like this, you are probably doing something wrong" or
"just don't do it this way".
Also, please don't tell me not to use it. I know about all the drawbacks of my current solution. Please only make comments about non-obvious drawbacks if you are really sure that I am not aware of that. Please don't just state that there are many drawbacks in my current solution. Please also don't state that it is not worse to use it. I am just asking if you know about a better solution than the one I have presented here.
Sometimes the only reason I have to implement a constructor is because of this.
You don't have to do that.
struct POD {
int i;
char ch;
};
POD uninitialized;
POD initialized = POD();
Equally in an initialization list:
class myclass
POD pod_;
// ....
myclass()
: pod_() // pod_'s members will be initialized
{
}
To overcome this, I try to use my own types instead.
Your type fails in this scenario:
void f(int&);
Num<int> i;
f(i);
There's likely more problems, but this is what occurred to me immediately.
How have you solved this? Any better solution?
Yes, we all have solved this. We did by not attempting to fight the language, but to use it the way it was created: initialize PODs in initialization lists. When I see this:
struct ML_LieroX : MapLoad {
std::string id;
PIVar(int, 0) type;
std::string themeName;
PIVar(int, 0) numObj;
PIVar(bool,false) isCTF;
I cringe. What is this doing? Why is it this way? Is this even C++?
All this just to save a few keystrokes typing an initialization list? Are you even serious?
Here's an old bon mot: A piece of code gets written once, but over its lifetime will be read tens, hundreds, or even thousands of times. That means that, in the long run, the time it takes to write a piece code is more or less neglectable. Even if it takes you ten times as long to write the proper constructors, but it saves me 10% of the time necessary to understand your code, then writing the constructors is what you should do.
Boost provides a value_initialized<T> template that can be used to ensure an object (POD or not) is value-initialized. Its documentation goes into great detail explaining the pros and cons of using it.
Your complaint about not being able to automatically initialize an object to a given value doesn't make much sense; that has nothing to do with the object being POD; if you want to initialize a non-POD type with a non-default value, you have to specify the value when you initialize it.
You could initialize POD structures as follows:
struct POD
{
int x;
float y;
};
int main()
{
POD a = {}; // initialized with zeroes
POD b = { 1, 5.0f }; // x = 1, y = 5.0f
return 0;
}
There is a proposal for C++0x which allows this:
struct A {
int x = 42;
};
That is exactly what I want.
If this proposal is not making it into the final version, the possibility of delegating constructors is another way of at least avoiding to recode the initialization in every single constructor (and at the same time avoiding a dummy helper function to do this).
In current C++, there does not seem to be any better way to do it despite what I have already demonstrated.
C++ does have constructor delegation, so why not use it?
struct AState
{
int x;
AState() : x(42) {}
};
class A : AState
{
A() {}
A(/*...*/) { /*...*/ }
A(/*...*/) { /*...*/ }
};
Now initialization of x is delegated by all constructors. The base constructor can even accept arguments passed from each version of A::A.
Prior to C++0x there is a solution which works well if the non-zero value you want to initialize with is not completely arbitrary (which is usually the case in practice). Similar to boost::initialized_value but with an extra argument to take the initial value (which gets a little fussy because C++).
template<typename T> struct Default { T operator()() { return T(); } };
template<typename T, T (*F)()> struct Call { T operator()() { return F(); } };
template<int N> struct Integer { int operator()() { return N; } };
template< typename X, typename Value = Default<X> >
class initialized {
public:
initialized() : x(Value()()) {}
initialized(const X& x_) : x(x_) {}
const X& get() const { return x; }
operator const X&() const { return x; }
operator X&() { return x; }
private:
X x;
};
You might use it like this:
struct Pi { double operator()() { return 3.14; } }; //Exactly
const char* init_message() { return "initial message"; }
Point top_middle() { return Point(screen_width()/2, 0); }
struct X {
initialized<int> a;
initialized<int, Integer<42> > b;
initialized<double> c;
initialized<double, Pi> d;
initialized<std::string> e;
initialized<std::string, Call<const char*, init_message> > f;
initialized<Point> g;
initialized<Point, Call<Point,top_middle> > h;
X() {}
};
I find the annoyance of having to create a dummy function to return any non-integral / non-default value is generally amortized across the entire library (since the non-zero initial values for a particular type are generally shared by many classes).
Obviously typedef is a friend here.
Anyway, can't wait to upgrade to C++0x/11/14/whatever.