Debugger-friendly zero-cost named references to specific locations in an array - c++

struct A
{
int a = 1;
short b = 2;
char c = 3;
}
struct B
{
using arr_type = array<A,3>;
char asd = 0;
A a1;
A a2;
A a3;
// is this safe to use to loop trough all 3 elements?
arr_type* p1 = reinterpret_cast<arr_type*>(&a1);
// or maybe this one?
A* p2 = &a1;
};
Can I safely use p1 or p2 to loop from a1...a3 ?
B b;
for (int i = 0; i < 3; i++)
{
cout << p1[i];
cout << p2[i];
}
The reason why it's not a simple array is because I want each "item" to have a proper name.
I could instead use the union approach, but the C++ prohibits anonymous structs (altho this is not a problem for me since MSVC supports this and GCC seems to support it as well);
union E
{
A arr[3];
struct {
A a1;
A a2;
A a3;
};
};
And the following is clearly safe, but it has a 4 byte overhead for each reference. Which I don't like. (Plus the cost to initialize the references..)
struct B
{
char asd;
A arr[3];
A& a1 = arr[0];
A& a2 = arr[1];
A& a3 = arr[2];
};
And this one has no overhead but for my very specific case, it's not good enough.
struct B
{
char asd;
A arr[3];
A& a1() { return arr[0] };
A& a2() { return arr[1] };
A& a3() { return arr[2] };
};
I'm gonna be using those a1, a2, a3 names very often, and it's harder to debug them if they are function calls in visual studio. And again, I'm going to be using those fields a lot, so I want to be able to check their values easily.

struct B
{
using arr_type = array<A,3>;
char asd = 0;
A a1;
A a2;
A a3;
// is this safe to use to loop trough all 3 elements?
arr_type* p1 = reinterpret_cast<arr_type*>(&a1);
};
Structs need to align naturally for their types, and so do arrays, but I don't know of any rule saying they have to be the same alignment points.
If there were such a rule that struct layout boundaries for members like this and array boundaries will be the same--it would only apply to standard layout structs:
https://stackoverflow.com/a/7189821/211160
All bets would be off if you did something like:
private:
A a1;
A a2;
public:
A a3;
I'd imagine all bets would be off if it contained anything that flipped off the standard layout switch. As it was questionable to start with, I'd say don't even do it then.
(I'd also wonder what kind of differences #pragma pack() would throw in for arrays vs. structs...not that #pragmas are in the standard, I just wonder.)
union E
{
A arr[3];
struct {
A a1;
A a2;
A a3;
};
};
No, arr[N] and aN would not be equivalent. There are some subtle details about how you can use initial sequences in unions for compatible reading in C++...but that's only between structures with compatible sequences. It says nothing about a struct and an array:
Type punning a struct in C and C++ via a union
I'm gonna be using those a1, a2, a3 names very often, and it's harder to debug them if they are function calls in visual studio. And again, I'm going to be using those fields a lot, so I want to be able to check their values easily.
"And the following is clearly safe, but it has a 4 byte overhead for each reference"
In practice it appears you are correct, that today's GCC isn't optimizing it out (per your links):
https://godbolt.org/g/6jAtD5
http://ideone.com/zZqfor
That's disappointing and they could be optimized out, as there's nothing in the standard saying they have to take up space. They point internally to the structure, and they don't change for the lifetime of the structure. :-/
Your complaint against the function access which would be optimized away was that it wasn't debugger-friendly enough. Why not do both?
struct B
{
char asd;
A arr[3];
A& a1() { return arr[0] }
const A& a1() const { return arr[0]; }
A& a2() { return arr[1] };
const A& a2() const { return arr[1]; }
A& a3() { return arr[2] };
const A& a3() const { return arr[2]; }
#if !defined(NDEBUG)
A& a1_debug = arr[0];
A& a2_debug = arr[1];
A& a3_debug = arr[2];
#endif
};
If debugger-friendliness features of projecting your data structures is important to you...it might be a good use of time to learn how to write custom debugger helpers for your environment, e.g.:
http://doc.qt.io/qtcreator/creator-debugging-helpers.html
I guess whether that's worth it depends on how often you have this kind of concern.

No need for such nastiness.
std::tuple coupled with a lambda gives you all the functionality you want. Plus it's perfectly legal, optimal and correct.
If we define a member function that returns a tuple of references to all As in the structure:
auto all_a() const {
return std::tie(a1, a2, a3);
}
...then create a little plumbing for provide a means to walk over the tuple (see below)...
... we can write code like this:
B b;
for_each(b.all_a(),
[](const A& a) { std::cout << a << std::endl; });
Full example (although I didn't implement operator<<, you can do that yourself).
#include<iostream>
#include<array>
#include<tuple>
#include<utility>
using namespace std;
struct A
{
int a = 1;
short b = 2;
char c = 3;
};
std::ostream& operator<<(std::ostream& os, const A& a);
struct B
{
char asd = 0;
A a1;
A a2;
A a3;
auto all_a() const {
return std::tie(a1, a2, a3);
}
};
template<class Tuple, size_t...Is, class F>
void for_each_impl(const Tuple& t, std::index_sequence<Is...>, F&& f)
{
using expand = int[];
void(expand { 0, (void(f(std::get<Is>(t))),0)... });
}
template<class...Ts, class F>
void for_each(const std::tuple<Ts...> ts, F&& f)
{
using expand = int[];
for_each_impl(ts,
std::make_index_sequence<sizeof...(Ts)>(),
std::forward<F>(f));
}
int main()
{
B b;
for_each(b.all_a(),
[](const A& a) { std::cout << a << std::endl; });
}

Related

Inherited std::array and aggregate initialization

I have a need to compare triplets of doubles that were calculated using different processes which causes them to differ by small amounts but should be considered equivalent. One approach that appears to work is to inherit std::array in such a way that the values can be compared within some delta of each other. This appears to work:
template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public std::array<double,3>
I also need to interop with standard arrays which requires a conversion constructor. However, it appears aggregate initialization is not allowed when a constructor is provided: aggregate initialization.
no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
But I have added this constructor which is needed when assigning from a regular array like b2 = a; in the code:
RGB(const std::array<double,3>& x) {*static_cast<std::array<double,3>*>(this) = x;}
Yet, this seems to work.
RGB<2> b2{{ 1,2,3 }};
Is this not aggregate initialization? Am I missing something?
#include <iostream>
#include <array>
#include <algorithm>
#include <vector>
using std::vector;
using std::array;
using std::cout;
template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public std::array<double,3>
{
public:
RGB(const std::array<double,3>& x) {*static_cast<std::array<double,3>*>(this) = x;}
friend bool operator==(const RGB& a, const RGB& b)
{
auto resolution = [](int prec)
{
double factor = 1.0;
while (prec--)
factor = factor / 10.0;
return factor;
};
constexpr double delta = resolution(precision_equals);
return a[0] < b[0] + delta && a[0] > b[0] - delta
&& a[1] < b[1] + delta && a[1] > b[1] - delta
&& a[2] < b[2] + delta && a[2] > b[2] - delta;
}
friend bool operator!=(const RGB& a, const RGB& b) { return !(a == b); }
};
int main()
{
// shows vector of inherited arrays can be sorted
vector<RGB<2>> v{ {{1,2.0001,3}}, {{1,2,3}} };
sort(v.begin(), v.end());
array<double, 3> a{ 1,2,3 };
RGB<2> b2{{ 1,2,3 }};
RGB<2> c2{{ 1.001,2,3 }};
RGB<3> b3{{ 1,2,3 }};
RGB<3> c3{{ 1.005,2,3 }};
// comparisons work
cout << "b2==c2: " << (b2 == c2 ? "true\n" : "false\n");
cout << "b3==c3: " << (b3 == c3 ? "true\n" : "false\n");
// assignments to/from regular arrays work
a = b2;
b2 = a;
}
Works in MSVC and GCC. Link to compiler explorer
#LanguageLawyer notes that an assignment conversion operator would remove most of the need for a conversion constructor. Removal of the conversion constructor and replacement by this
RGB& operator=(const std::array<double, 3>& from)
{
//return *this = *static_cast<const RGB*>(&from); // UB
(*this)[0] = from[0]; // ugly version that's not UB
(*this)[1] = from[1];
(*this)[2] = from[2];
return *this;
}
allows the code to compile so my use case is solved. However, the question whether the conversion constructor prohibits aggregate initialization remains.
Calling base constructor should be better
Untested code
RGB(const std::array<double,3>& x) : std::array<double, 3>(x) {}
or a slight rewrite
using BaseRGB = std::array<double,3>;
template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public BaseRGB {
public:
RGB(const BaseRGB& x) : BaseRGB(x) {}
// or even
using BaseRGB::BaseRGB; // using the constructor directly if you don't set up anything more.

Uninitialized value when dealing with shared_ptr

I'm sure this is very simple, but I'm rather new to smart pointers, and I couldn't find an answer to this.
Scenario is very simple:
I have a class A, that holds a shared_ptr to some object X:
class A{
shared_ptr<const X> _asX;
}
now after a series of function calls, I'm creating a new object of type B, that also holds this X. something like:
class B {
private:
shared_ptr<const X> _bsX;
public:
B(): _bsX(nullptr) // - maybe this is problematic {}
foo(shared_ptr<const X>& x)
{
_bsX = x;
// The line above gives me undefined behavior,
// and when I run valgrind I get "Conditional jump or move
// depends on uninitialized value(s)",
// telling me this is not the correct way to do things.
}
Note that it is deliberate the foo really sets the value of _bsX and not the constructor.
So as stated above - depending on the compiler, I something get segmentation faults - which usually means some value was not initialized, and later confirmed by valgrind.
So what should I do - I've tried using 'reset' etc. but I got so confused I'm asking for your help.
Could it be the const ? or the pass by reference ? or the '=' operator.
And while we're at it - should I be passing X with its wrapper (the shared_ptr) to foo, or should I pass the raw pointer, and then make it shared ? if so - could you please give an example. I tried that as well, and got errors.
Ok, I found the problem, and it's no related to smart pointers at all, but since I'm new to this - I thought it might be.
I'll leave this answer for future references. This is what I did (simplified):
class A{
private:
shared_ptr<const int> _num;
public:
A()
{
_num = make_shared<const int>(5);
}
const shared_ptr<const int>& getNum() const {return _num; }
void printNum()
{
cout << *_num.get() << endl;
}
};
class B
{
public:
struct C{
C() : _num(nullptr){}
void boo(shared_ptr<const int> & num) { _num = num;}
shared_ptr<const int> _num;
};
B() {}
void foo(shared_ptr<const int>& num)
{
cs.reserve(2);
for (uint32_t i = 0; i < 2 ; ++i) {
cs.push_back(C()); // This was missing.
cs[i].boo(num);
}
}
void printCNum()
{
for (C c : cs) {
cout << *c._num.get() << endl;
}
}
private:
vector<C> cs;
};
int main()
{
A a{};
shared_ptr<const int> xx = a.getNum();
B b{};
b.foo(xx);
a.printNum();
b.printCNum();
}
Silly me, I thought that when you reserve a vector of Objects (not pointers/references) it also calls their constructor. It turn out it's not. Specifically, I increased the capacity of the vector, but not its size.

automatic calling custom converter of raw pointers A* <-> B*

Is it possible to define a custom converter (converter1<T> and converter2) between different types of raw pointer A* and B*,
then make all functions (fa() and fb()) in a certain class
use an appropriate converter (converter1<T> or converter2)?
In short, I want the program to convert A* to B* and vice versa USING my custom functions.
I wish it would do that automatically for my convenience.
class Manager{
void fb(B* b){ /** something complex */ }
void fa(A* a){ /** different thing complex */ }
void testCase(){
A* a= ... ;
fa(a);
fb(a); //automatic convert to B* using "converter2" (wish)
B* b= ... ;
fa(b); //automatic convert to A* using "converter1" (wish)
fb(b);
}
template<class T> T* converter1(B* b){ //hardcoded, non-static.
return this->getId<T>(b);
//^^^ just an example to show how custom it is,
// currently T=A
}
B* converter2(A* a){ //hardcoded
return a->getB();
//^^^ just an example to show how custom it is.
}
}
The real case has many A - A1, A2, A3 and so on.
A and B are not derived from each other.
I wish there is a way. I think about constructor of pointer.
No this is not possible.
Pointers are built-in types and only built-in conversions between built-in types exist. User-defined conversions only work for user-defined class types.
You may want to switch to your own brand of smart pointers to handle this.
through references (or smart pointers) it's more possible:
struct A {};
struct B {};
A& convert_to_a(A& a) { return a; }
A convert_to_a(B const& b) {
// makes a new A from a B
return A();
}
B& convert_to_b(B& b) { return b; }
B convert_to_b(A const& a) { return B(); }
struct Manager
{
template<class T>
void fa(T&& t) {
auto&& a = convert_to_a(t);
// do something with a
(void)a;
}
template<class T>
void fb(T&& t) {
auto&& b = convert_to_b(t);
// do something with b
(void)b;
}
};
int main()
{
A a;
B b;
Manager m;
m.fa(a);
m.fb(a);
m.fa(b);
m.fb(b);
}
It is not possible the way you want it.
Anyway, you can use a catch-all function and a bunch of traits to simulate it.
It follows a minimal, working example:
#include<iostream>
struct A {};
struct B {};
template<typename T>
A* ToAConverter(T*) = delete;
template<>
A* ToAConverter<B>(B *b) {
// just an example
return new A;
}
struct Manager{
void fa(A* a){ std::cout << "fa" << std::endl; }
template<typename T>
void fa(T *t) {
std::cout << "convert and forward" << std::endl;
fa(ToAConverter<T>(t));
}
void testCase(){
A *a = new A;
fa(a);
B *b = new B;
fa(b);
}
};
int main() {
Manager m;
m.testCase();
}
In case you haven't defined a converter for a specific type, you'll receive a compile-time error.
As you can see, you have no longer to call explicitly the converter when you invoke fa.

Pointer Wrapper: dereference operator

I'm pretty new to C++ and as an exercise (and perhaps eventually .Net utility) I'm doing a pointer wrapper (actually in C++/CLI, but this applies to C++ as well). This pointer wrapper (called Apont) currently behaves just like a pointer would, as the test below can show, if lines marked 1. and 2. are commented out:
int main(array<System::String ^> ^args)
{
double ia = 10; double ip = 10;
double *p = &ip; // pointer analogy
Apont<double> ^a =
gcnew Apont<double>(ia); // equivalent to what's below, without errors
a = ~ia;/* 1. IntelliSense: expression must have integral or unscoped enum type
error C2440: '=' : cannot convert from 'double' to 'Utilidades::ComNativos::Apont<T> ^'
error C2171: '~' : illegal on operands of type 'double'*/
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
ia = 20; ip = 20;
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
*p = 30; // pointer analogy
a->Valor = 30; // does exacly what's below, without errors
!a = 30;/* 2. IntelliSense: expression must be a modifiable lvalue
error C2106: '=' : left operand must be l-value */
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
//a->Dispose();
Console::ReadKey();
p = nullptr;
return 0;
}
There are two things I don't like here, marked with 1. and 2. in the code comments, before the lines with errors. The operator~ (see 1.) is defined outside Apont, below:
template<typename T> static Apont<T>^% operator ~(T& valor)
{
return gcnew Apont<T>(valor);
}
I think this one has to be defined outside Apont, but I'm not sure. I cannot understand very well the errors it produces (these are, of course, in the use, not in the definition).
To set the value to which the instance of Apont refers I must use a property (the line marked 2. doesn't work, with errors in the setting usage only), Apont::Valor, which is the equivalent to use *p. What I'd like to do is as I use *p to get or set the value it points to, use !a with the same effect on Apont. Here's Apont::operator!()'s current definition:
T operator !()
{
return Valor;
}
As you can see in 2. (comment in the code, before the respective errors), it doesn't work for setting a value. Maybe I should return a reference? Make another operator with the same name, perhaps outside the class? I tried several options, however, I got similar errors, and came out more confused.
The question is: how can I make an operator that behaves like & (in this case, ~) and one that behaves like * (in this case, !, for dereference, but that behaves like Apont::Valor, whose old definition you can see below)?
property T Valor
{
T get()
{
if (pointer != nullptr)
return *pointer;
else if (eliminado && ErroSeEliminado) // means "disposed && ErrorIfDisposed"
throw gcnew ObjectDisposedException("O objeto já foi pelo menos parcialmente eliminadao.");
else if (ErroSeNulo) // means "ErrorIfNull"
throw gcnew NullReferenceException();
else
return 0;
// don't worry, this is not default behavior, it is returned only if you want to ignore all errors and if the pointer is null
}
void set(T valor)
{
*pointer = valor;
}
}
Let me recap in a new answer for clarity.
Solving the ! operator is easy, as I said in my previous answer, just add a reference.
So for the operator ~, the goal was to have it behave like the & operator and call the constructor of the pointer wrapper class.
I don't think that is possible. It is certainly possible for user defined objects, but I don't think it is possible to overload unary operators for builtin types. So there are three solutions depending on what you prefer:
The first one does exactly what you want, but will break for primitive types:
#include <iostream>
template<typename T>
struct A {
T* payload;
A()
: payload(NULL){}
A(T *ptr)
: payload(ptr) {}
T& operator !(){
return *payload;
}
};
// this will not work for primary types
template<typename T>
A<T> operator ~(T &b){
return A<T>(&b);
}
struct B{
int test;
};
int main(){
B b; b.test = 4;
A<B> a;
a = ~b; // I think this is what you want
std::cerr << (!a).test << std::endl;
// this does not work
//int i = 4;
//A<int> a;
//a = ~i;
}
Second solution: use a compound assignment operator. Pros are the side effects are minimal, cons is this is not very intuitive and might break the nice design you had in mind.
#include <iostream>
template<typename T>
struct A {
T* payload;
A() : payload(NULL){}
T& operator !(){
return *payload;
}
};
template<typename T>
A<T>& operator &=(A<T> &a, T& b){ // should be friend of the above
a.payload = &b;
return a;
}
int main(){
int i = 3;
A<int> a;
a &= i;
std::cerr << !a << std::endl;
}
Third solution: overload the basic assignment operator. This is more intuitive to write but has a lot of side effects:
#include <iostream>
template<typename T>
struct A {
T* payload;
A() : payload(NULL){}
T& operator !(){
return *payload;
}
A<T>& operator = (T & b) {
payload = &b;
return *this;
}
};
int main(){
int i = 3;
A<int> a;
a = i;
std::cerr << !a << std::endl;
}
Someone might have a solution to hijack the operators for primitive types, but i can't think of any simple solution.
If i understood your code correctly, you want the operator ~ to return a copy of the pointer wrapper and the operator ! to act as dereference?
In this case, you can define the unary operator ~ inside the Apont class which calls a copy constructor. And the operator ! has to return a reference indeed if you want to asign a value.
I think the following c++ code defines what you want to do (I renamed Apont to A):
#include <iostream>
template<typename T>
struct A {
T* payload;
A(T *ptr)
:payload(ptr) {}
A(const A&other)
:payload(other.payload) {}
T& operator !(){
return *payload;
}
T* operator ~(){
return payload;
}
};
int main(){
#define PRINT(X) std::cerr << #X << " = " << X << std::endl
int i = 0;
PRINT(i);
A<int> a(&i);
!a = 1;
PRINT(i);
A<int> b = ~a;
!b = 2;
PRINT(i);
}
The output of the code above is:
i = 0
i = 1
i = 2
According to your comments, you said you wanted the operator ! to behave exactly like the wrapped pointer. You can do so, but then the syntax changes and you need to dereference it to assign a new value (because it is a pointer...). ie something like:
#include <iostream>
template<typename T>
struct A {
T* payload;
A(T *ptr): payload(ptr) {}
// this now behaves like accessing the wrapped pointer directly
T*& operator !(){
return payload;
}
};
int main(){
#define PRINT(X) std::cerr << #X << " = " << X << std::endl
int i = 0;
int j = 999;
PRINT(i);
A<int> a(&i);
*(!a) = 1; // note the change of syntax here
PRINT(*!a); // and here
!a = &j; // but now you can change the wrapped pointer through the operator
PRINT(*!a);
}

C++: constructor initializer for arrays

I'm having a brain cramp... how do I initialize an array of objects properly in C++?
non-array example:
struct Foo { Foo(int x) { /* ... */ } };
struct Bar {
Foo foo;
Bar() : foo(4) {}
};
array example:
struct Foo { Foo(int x) { /* ... */ } };
struct Baz {
Foo foo[3];
// ??? I know the following syntax is wrong, but what's correct?
Baz() : foo[0](4), foo[1](5), foo[2](6) {}
};
edit: Wild & crazy workaround ideas are appreciated, but they won't help me in my case. I'm working on an embedded processor where std::vector and other STL constructs are not available, and the obvious workaround is to make a default constructor and have an explicit init() method that can be called after construction-time, so that I don't have to use initializers at all. (This is one of those cases where I've gotten spoiled by Java's final keyword + flexibility with constructors.)
Edit: see Barry's answer for something more recent, there was no way when I answered but nowadays you are rarely limited to C++98.
There is no way. You need a default constructor for array members and it will be called, afterwards, you can do any initialization you want in the constructor.
Just to update this question for C++11, this is now both possible to do and very natural:
struct Foo { Foo(int x) { /* ... */ } };
struct Baz {
Foo foo[3];
Baz() : foo{{4}, {5}, {6}} { }
};
Those braces can also be elided for an even more concise:
struct Baz {
Foo foo[3];
Baz() : foo{4, 5, 6} { }
};
Which can easily be extended to multi-dimensional arrays too:
struct Baz {
Foo foo[3][2];
Baz() : foo{1, 2, 3, 4, 5, 6} { }
};
Right now, you can't use the initializer list for array members. You're stuck doing it the hard way.
class Baz {
Foo foo[3];
Baz() {
foo[0] = Foo(4);
foo[1] = Foo(5);
foo[2] = Foo(6);
}
};
In C++0x you can write:
class Baz {
Foo foo[3];
Baz() : foo({4, 5, 6}) {}
};
Unfortunately there is no way to initialize array members till C++0x.
You could use a std::vector and push_back the Foo instances in the constructor body.
You could give Foo a default constructor (might be private and making Baz a friend).
You could use an array object that is copyable (boost or std::tr1) and initialize from a static array:
#include <boost/array.hpp>
struct Baz {
boost::array<Foo, 3> foo;
static boost::array<Foo, 3> initFoo;
Baz() : foo(initFoo)
{
}
};
boost::array<Foo, 3> Baz::initFoo = { 4, 5, 6 };
You can use C++0x auto keyword together with template specialization on for example a function named boost::make_array() (similar to make_pair()). For the case of where N is either 1 or 2 arguments we can then write variant A as
namespace boost
{
/*! Construct Array from #p a. */
template <typename T>
boost::array<T,1> make_array(const T & a)
{
return boost::array<T,2> ({{ a }});
}
/*! Construct Array from #p a, #p b. */
template <typename T>
boost::array<T,2> make_array(const T & a, const T & b)
{
return boost::array<T,2> ({{ a, b }});
}
}
and variant B as
namespace boost {
/*! Construct Array from #p a. */
template <typename T>
boost::array<T,1> make_array(const T & a)
{
boost::array<T,1> x;
x[0] = a;
return x;
}
/*! Construct Array from #p a, #p b. */
template <typename T>
boost::array<T,2> make_array(const T & a, const T & b)
{
boost::array<T,2> x;
x[0] = a;
x[1] = b;
return x;
}
}
GCC-4.6 with -std=gnu++0x and -O3 generates the exact same binary code for
auto x = boost::make_array(1,2);
using both A and B as it does for
boost::array<int, 2> x = {{1,2}};
For user defined types (UDT), though, variant B results in an extra copy constructor, which usually slow things down, and should therefore be avoided.
Note that boost::make_array errors when calling it with explicit char array literals as in the following case
auto x = boost::make_array("a","b");
I believe this is a good thing as const char* literals can be deceptive in their use.
Variadic templates, available in GCC since 4.5, can further be used reduce all template specialization boiler-plate code for each N into a single template definition of boost::make_array() defined as
/*! Construct Array from #p a, #p b. */
template <typename T, typename ... R>
boost::array<T,1+sizeof...(R)> make_array(T a, const R & ... b)
{
return boost::array<T,1+sizeof...(R)>({{ a, b... }});
}
This works pretty much as we expect. The first argument determines boost::array template argument T and all other arguments gets converted into T. For some cases this may undesirable, but I'm not sure how if this is possible to specify using variadic templates.
Perhaps boost::make_array() should go into the Boost Libraries?
This seems to work, but I'm not convinced it's right:
#include <iostream>
struct Foo { int x; Foo(int x): x(x) { } };
struct Baz {
Foo foo[3];
static int bar[3];
// Hmm...
Baz() : foo(bar) {}
};
int Baz::bar[3] = {4, 5, 6};
int main() {
Baz z;
std::cout << z.foo[1].x << "\n";
}
Output:
$ make arrayinit -B CXXFLAGS=-pedantic && ./arrayinit
g++ -pedantic arrayinit.cpp -o arrayinit
5
Caveat emptor.
Edit: nope, Comeau rejects it.
Another edit: This is kind of cheating, it just pushes the member-by-member array initialization to a different place. So it still requires Foo to have a default constructor, but if you don't have std::vector then you can implement for yourself the absolute bare minimum you need:
#include <iostream>
struct Foo {
int x;
Foo(int x): x(x) { };
Foo(){}
};
// very stripped-down replacement for vector
struct Three {
Foo data[3];
Three(int d0, int d1, int d2) {
data[0] = d0;
data[1] = d1;
data[2] = d2;
}
Foo &operator[](int idx) { return data[idx]; }
const Foo &operator[](int idx) const { return data[idx]; }
};
struct Baz {
Three foo;
static Three bar;
// construct foo using the copy ctor of Three with bar as parameter.
Baz() : foo(bar) {}
// or get rid of "bar" entirely and do this
Baz(bool) : foo(4,5,6) {}
};
Three Baz::bar(4,5,6);
int main() {
Baz z;
std::cout << z.foo[1].x << "\n";
}
z.foo isn't actually an array, but it looks about as much like one as a vector does. Adding begin() and end() functions to Three is trivial.
Only the default constructor can be called when creating objects in an array.
In the specific case when the array is a data member of the class you can't initialize it in the current version of the language. There's no syntax for that. Either provide a default constructor for array elements or use std::vector.
A standalone array can be initialized with aggregate initializer
Foo foo[3] = { 4, 5, 6 };
but unfortunately there's no corresponding syntax for the constructor initializer list.
There is no array-construction syntax that ca be used in this context, at least not directly. You can accomplish what you're trying to accomplish by something along the lines of:
Bar::Bar()
{
static const int inits [] = {4,5,6};
static const size_t numInits = sizeof(inits)/sizeof(inits[0]);
std::copy(&inits[0],&inits[numInits],foo); // be careful that there are enough slots in foo
}
...but you'll need to give Foo a default constructor.
Ideas from a twisted mind :
class mytwistedclass{
static std::vector<int> initVector;
mytwistedclass()
{
//initialise with initVector[0] and then delete it :-)
}
};
now set this initVector to something u want to before u instantiate an object. Then your objects are initialized with your parameters.
You can do it, but it's not pretty:
#include <iostream>
class A {
int mvalue;
public:
A(int value) : mvalue(value) {}
int value() { return mvalue; }
};
class B {
// TODO: hack that respects alignment of A.. maybe C++14's alignof?
char _hack[sizeof(A[3])];
A* marr;
public:
B() : marr(reinterpret_cast<A*>(_hack)) {
new (&marr[0]) A(5);
new (&marr[1]) A(6);
new (&marr[2]) A(7);
}
A* arr() { return marr; }
};
int main(int argc, char** argv) {
B b;
A* arr = b.arr();
std::cout << arr[0].value() << " " << arr[1].value() << " " << arr[2].value() << "\n";
return 0;
}
If you put this in your code, I hope you have a VERY good reason.
This is my solution for your reference:
struct Foo
{
Foo(){}//used to make compiler happy!
Foo(int x){/*...*/}
};
struct Bar
{
Foo foo[3];
Bar()
{
//initialize foo array here:
for(int i=0;i<3;++i)
{
foo[i]=Foo(4+i);
}
}
};
in visual studio 2012 or above, you can do like this
struct Foo { Foo(int x) { /* ... */ } };
struct Baz {
Foo foo[3];
Baz() : foo() { }
};
class C
{
static const int myARRAY[10]; // only declaration !!!
public:
C(){}
}
const int C::myARRAY[10]={0,1,2,3,4,5,6,7,8,9}; // here is definition
int main(void)
{
C myObj;
}