C++ constructor initialization list invokes default constructor. Why? - c++

take a look at my code. It will convert Vector4 to Vector4.
There is this copy constructor, which automatically does the conversion component by component. I can't understand one thing: why at the end of construction, when each component is correctly set up, default constructor is invoked on each component making output vector empty. You can see execution flow in the output below. Interesting is, that if I replace initialization list by 4 assignments, the code works as expected.
Compiler is VS2013.
#include <cstdio>
using namespace std;
struct half
{
unsigned short data;
half() : data(0) { printf("half::default_constructor\n"); }
half(half& pattern) : data(pattern.data) { printf("half::copy_constructor\n"); }
explicit half(float pattern) : data(16) { printf("half::from_float_constructor\n"); }
operator float() { printf("half::to_float_operator\n"); return 3.0f; }
};
template <typename T>
struct Vector4
{
Vector4() : x(0), y(0), z(0), w(0) { }
Vector4(T value) : x(value), y(value), z(value), w(value) { }
Vector4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) { }
template <typename U>
Vector4(Vector4<U>& other) : x((T)other.x), y((T)other.y), z((T)other.z), w((T)other.w) { }
union
{
struct { T x, y, z, w; };
struct { T r, g, b, a; };
};
};
int main()
{
Vector4<float> a(0, 1, 4, 6);
Vector4<half> b(a);
}
Output from this program:
half::from_float_constructor
half::to_float_operator
half::from_float_constructor
half::from_float_constructor
half::to_float_operator
half::from_float_constructor
half::from_float_constructor
half::to_float_operator
half::from_float_constructor
half::from_float_constructor
half::to_float_operator
half::from_float_constructor
half::default_constructor
half::default_constructor
half::default_constructor
half::default_constructor

The reason is that the code is invalid. You cannot store non-POD types in a union. Your code results in undefined behaviour. I don’t know exactly what the compiler does as a result, and why it invokes the default constructor1 – but that’s undefined behaviour for you.
1 Although I have a theory: it probably attempts to initialise r, g, b and a.

First of all C++ has no anonymous structures. So this definition of Vector4 member
union
{
struct { T x, y, z, w; };
struct { T r, g, b, a; };
};
is not C++ compliant. I think you use MS VC++ that has such language extension.
Now let consider what occurs.
In mem-initializer list of the template constructor
template <typename U>
Vector4(Vector4<U>& other) : x((T)other.x), y((T)other.y), z((T)other.z), w((T)other.w) { }
C-style casting as for example (T)other.x invokes constructor of class half
explicit half(float pattern) : data(16) { printf("half::from_float_constructor\n");
The result of this call is creating a temporary object of type half
You may not apply the copy constructor of class half because its parameter is declared as non-const reference and temporary objects may not bind to non-const references.
half(half& pattern) : data(pattern.data) { printf("half::copy_constructor\n"); }
So the constructor searches other paths to do the task.
It can convert the temporary object to an object of type float
operator float() { printf("half::to_float_operator\n"); return 3.0f; }
};
that to call at last constructor
explicit half(float pattern) : data(16) { printf("half::from_float_constructor\n"); }
Thus you get the following sequence of messages
half::from_float_constructor
half::to_float_operator
half::from_float_constructor
I prepared a more simple C++ compliant example that demonstrates the same behaviour
#include <iostream>
struct A
{
float x = 0.0f;
};
struct B
{
explicit B( float ){ std::cout << "B::from_float_constructor" << std::endl; }
B( B & ){ std::cout << "B::from_copy_constructor" << std::endl; }
operator float () const
{
std::cout << "B::to_float_operator" << std::endl;
return 0.0f;
}
};
struct C
{
B b;
C( A a ) : b( ( B )a.x ) {}
};
int main()
{
A a;
C c( a );
return 0;
}
The output is
B::from_float_constructor
B::to_float_operator
B::from_float_constructor

Related

Prevent initialization with parentheses or braces

Given a class C, is it possible to prevent construction using parenthesis (e.g. forbid C c(1);) or braces (e.g. forbid C c{1};)?
I am interested in the question per se, but since it got asked what is my motivation:
I do not like the following behaviours:
#include <array>
struct aggregate{ int x,y; };
int main() {
aggregate A{1};
std::array< aggregate, 2 > B{1,2,3};
}
which yields
A.x=1, A.y=0
B[0].x=1, B[0].y=2,B[1].x=3, B[1].y=0
The first one is at least kind of reasonable, the second one not at all. I rather would like to have a compile time error for both of them.
My goal is to write a container array similar to (and as efficient as) std::array which prevents such bad constructions.
To be constructed like:
#include <array>
struct aggregate{ int x,y; };
int main() {
array< aggregate, 2 > A; // all elements default initialized
array< aggregate, 2 > B{aggregate{1,2},aggregate{3,4}};
array< aggregate, 2 > C{{1,2},{3,4}}; // would be nice but not mandatory
// everything below here should yield compile time errors
array< aggregate, 2 > D(1,2);
array< aggregate, 2 > D{1,2};
array< aggregate, 2 > D({1,2});
array< aggregate, 2 > D(1,2,3,4);
array< aggregate, 2 > D{1,2,3,4};
// etc...
}
To further detalize my motivation (since it seems, my question is not going to be answered): I am not so concerned about the class aggregate given above, but about the class array. Thus, it is not an option to remove/add ctors from the class.
So far I have the following code:
It prevents nearly all of my unwanted initializations, except that it calls unnecessary often a ctor. So my idea is: In Debug mode I typedef array to the class tmm::array`` in the code below, in Release mode I typedef it to std::array. But the problem arises that tmm::arrayallows constructs which are not allowed forstd::array`.
#include <array>
#include <iostream>
#include <type_traits>
template <typename T, typename ...Ts>
inline constexpr bool areT_v = std::conjunction_v<std::is_same<T,Ts>...>;
struct CLASS {
int x, y;
CLASS() noexcept {
std::cout << "default constructed" << std::endl;
}
CLASS(int x_,int y_) noexcept : x(x_), y(y_) {
std::cout << "constructed" << std::endl;
}
CLASS( CLASS const & other ) noexcept : x(other.x), y(other.y) {
std::cout << "copy constructed" << std::endl;
}
};
namespace tmm {
template< typename T, int rows >
struct array
{
template< typename ... L > constexpr inline
array( L && ... lst ) noexcept : content{ std::forward< L >( lst ) ... } {
static_assert( sizeof...(L) == rows || sizeof...(L)==0 );
static_assert( areT_v<T,L...>, "" );
}
array() = default; // not sure whether I need this one
T content[rows];
};
}
int main() {
#define INIT CLASS{1,2},CLASS{3,4},CLASS{5,6}
std::array<CLASS,3>tb3b {INIT}; // 3 ctors
tmm::array<CLASS,3> sb3b {INIT}; // 3 ctors and 3 copy ctors
// std::array<CLASS,3> sp3a (INIT); // does not compile
tmm::array<CLASS,3>tp3a (INIT); // compiles
}
Given a class C, is it possible to prevent construction using parenthesis (e.g. forbid C c(1);) or braces (e.g. forbid C c{1};)?
To answer your question directly, the object of class C will only be constructible with the constructors you provide. That is, if C does not have a constructor from a single int, it won't be constructible using either C c(1); or C c{1}; syntax.
There are a few caveats, especially given your later explanation. First, if your class C is an aggregate then it follows the standard language rules for initialization (that is, it allows aggregate initialization). You cannot have an aggregate class and prohibit its aggregate initialization at the same time. The only way around it is to specify the constructors you want to allow, at which point the class is no longer an aggregate:
struct C
{
int x,y;
C() : x(0), y(0) {}
C(int x, int y) : x(x), y(y) {}
};
C a(10); // error - no constructor from a single int
Next, type conversions may still happen as part of initialization. If you also want to prohibit those, you may use deleted constructors or SFINAE. For example:
struct C_no_float
{
int x,y;
C_no_float() : x(0), y(0) {}
C_no_float(int x, int y) : x(x), y(y) {}
C_no_float(double x, double y) = delete;
};
C_no_float a(10, 20); // ok
C_no_float b(1.0, 2.0); // error - calling a deleted constructor
Note that using deleted functions may still be error-prone since the constructor from ints may still be called as a result of type conversion. In other words, this approach does not guarantee that C_no_float is not constructible from anything but exactly a pair of ints. Using SFINAE allows for stronger restriction on argument types:
struct C_only_int
{
int x,y;
C_only_int() : x(0), y(0) {}
template< typename T, typename = std::enable_if_t<std::is_same_v<T, int>> >
C_only_int(T x, T y) : x(x), y(y) {}
};
C_only_int a(10, 20); // ok, T is int
C_only_int b(10l, 20l); // error - T would be long,
// template argument substitution fails

static_cast on custom class causes copy assignment to fail

I expected the following program to print "11" but it actually prints "01" so it seems like the first assignment fails.
struct A
{
A(int i = 0) : i_(i) {}
int i_;
};
int main()
{
A x(1);
A y;
static_cast<A>(y) = x; // *** Fails to assign ***
std::printf("%i", y.i_);
y = x;
std::printf("%i", y.i_);
}
If I use a primitive type likeint instead of A then int x = 1; int y; static_cast<int>(y) = x; does assign the value 1 to x. Is there some way I can get it to work for custom types? I tried adding operator A() { return *this; } to struct A but that didn't work.
Obviously this is a stupid program but the problem arises in a template function where I have static_cast<std::remove_const<T>::type>(y) = x and it was working fine for primitive types but just now failed for a custom type.
As with any cast, static_cast<A>(y) is a temporary copy of y. You can cast to a reference type instead (static_cast<A&>(y)); more generally, you could achieve this with std::add_lvalue_reference.
For the more specific example you described, you'll need const_cast rather than static_cast, but the basic principle is the same.
Here's an example that compiles, but has UB because of the modification of a const object (and thus returns 0, not 42). Without knowing more about what you're trying to do, I shan't attempt to disguise that for the purposes of this example:
#include <iostream>
#include <type_traits>
template <typename T>
T foo(T val)
{
T x{};
using not_const = typename std::remove_const<T>::type;
using ref_type = typename std::add_lvalue_reference<not_const>::type;
const_cast<ref_type>(x) = val;
return x;
}
int main()
{
std::cout << foo<const int>(42) << '\n';
}

How to direct "c.foo()+c.boo()" to "c.foo_and_boo()"?

There is a class C with methods foo, boo, boo_and_foo and foo_and_boo. Each method takes i,j,k and l clock cycles respectively, where i < j, k < i+j and l < i+j.
class C
{
public:
int foo() {...}
int boo() {...}
int boo_and_foo() {...}
int foo_and_boo() {...} };
In code one might write:
C c;
...
int i = c.foo() + c.boo();
But it would be better to have:
int i = c.foo_and_boo();
What changes or techniques could one make to the definition of C, that would allow similar syntax of the original usage, but instead have the compiler generate the latter.
Note that foo and boo are not commutative.
Idea 1 Thanks the comments!
I was thinking creater a cHelper class, and a cOps class with string member ops, so that after have cHelper ch;, we can write int i = ch.foo() + ch.boo();
ch.foo() does nothing but returns: cOps("foo")
ch.boo() also only returns: cOps("boo")
overload "+" operator for cOps class so that cOps("foo") + cOps("boo") actually returns cOps("foo,boo")
overload the int type conversion operator of cOps so that int i = cOps("foo") ; actually calls c.foo(); while int i = cOps("foo,boo") ; actually calls c.foo_and_boo();
A bit ugly ....
The objective sounds rather similar to what Todd Veldhuizen pioneered many moons ago for Blitz++: aggregating operations effectively into an expression tree to effectively change the order of computations. In the case of Blitz++ it was done for matrix operations. The technique is known as Expression Templates.
The overall idea would not be to aggregate a string and its operations, though, but rather to encode the necessary operations in the type returned. Similar to what is described in the question the evaluation of the expression is delayed until they are needed. By using specializations for specific operations the compiler would be made to choose the appropriate combations. It could look somewhat like this:
#include <iostream>
namespace C_ops { struct C_tag {}; }
struct C_foo;
struct C_bar;
class C: C_ops::C_tag {
int value;
public:
explicit C(int value): value(value) {}
C_foo foo() const;
C_bar bar() const;
int actual_foo() const {
std::cout << "compute foo(" << value << ")\n";
return value;
}
int actual_bar() const {
std::cout << "compute bar(" << value << ")\n";
return value;
}
int foo_and_bar(C const& r) const {
std::cout << "compute foo_and_bar(" << this->value << ", " << r.value << ")\n";
return this->value;
}
int bar_and_foo(C const& r) const {
std::cout << "compute bar_and_foo(" << this->value << ", " << r.value << ")\n";
return this->value;
}
};
struct C_foo: C_ops::C_tag {
C const& c;
C_foo(C const& c): c(c) {}
operator int() const { return c.actual_foo(); }
};
struct C_bar: C_ops::C_tag {
C const& c;
C_bar(C const& c): c(c) {}
operator int() const { return c.actual_bar(); }
};
C_foo C::foo() const { return C_foo(*this); }
C_bar C::bar() const { return C_bar(*this); }
template <typename L, typename R>
struct C_add;
template <>
struct C_add<C_foo, C_bar> {
C_foo l;
C_bar r;
C_add(C_foo const& l, C_bar const& r): l(l), r(r) {}
operator int() const { return l.c.foo_and_bar(r.c); }
};
template <>
struct C_add<C_bar, C_foo> {
C_bar l;
C_foo r;
C_add(C_bar const& l, C_foo const& r): l(l), r(r) {}
operator int() const { return l.c.bar_and_foo(r.c); }
};
// more specializations, e.g., to deal with C on the LHS
namespace C_ops {
template <typename L, typename R>
C_add<L, R> operator+(L const& l, R const& r) {
return C_add<L, R>(l, r);
}
}
template <typename... T> void use(T const&...) {}
int main()
{
C c0(0), c1(1);
int r0 = c0.foo();
int r1 = c0.bar();
int r2 = c0.foo() + c1.bar();
int r3 = c0.bar() + c1.foo();
std::cout << "done\n";
use(r0, r1, r2, r3); // make them used to not have them optimized away (for now)
}
With the setup above, the four expressions you mentioned would be covered. There are probably more specializations needed, e.g., to all c + c.foo(), c + c, etc. but the overall principle doesn't really change. You may want to protect actual_foo() and actual_bar() from being accessed and making the respective classes needing to call the friends.
The need for the extra namespace C_ops is merely to provide "catch-all" operators which hijack operator+() for all types, as long as they happen to be loooked up in this namespace. To do so, there is also a tag-type which has no other purpose than directing ADL (argument dependent look-up) to look into this namespace.
This is quite a cute technique which worked rather reliably with C++03: since the expressions are evaluated when the target type (in the above case int) is needed and C++03 didn't really allow for capturing the intermediate type while potentially involved temporary object were not around any more (the only was to catch the expression type in a deduced context would be when passing it to a function template) there were no life-time issues. With C++11 it is to capture the type of objects using auto which would capture the expression type, not evaluated result, there is probably some need to think properly about life-time of involved objects. The above example just used const objects but you'll probably need to be more careful and prevent certain temporary objects from being capture, primarily objects of type C. From your descriptions it isn't clear whether these would be expensive objects: the ideal solution would be to capture all objects by value but that may be too expensive.

Automatic determination of the constructor initialization list by the compiler?

I was asking myself (and couldn't find an answer) if the modern C++ compilers could check into the body of the constructors to see if they could infer the initialization list, instead of letting the developer specifying it?
As an example, consider the following code:
MyClass::MyClass (Obj o)
{
_o = o;
}
Can the compiler automatically translate it into:
MyClass::MyClass (Obj o) : _o(o)
{}
Thanks
This is not possible as it completely changes the semantics of the program in the general case. Some of the examples:
// Order of evaluation:
struct Foo {
int a, b;
Foo() : b(a) { a = 1; } // differs from Foo() : a(1), b(a) {}
};
// Legality of the operation:
struct X { explicit X(int x); };
struct Foo {
X x;
Foo() { x = 5; } // Ill formed, while Foo() : x(5) is well formed
};
// Different effects even if allowed
struct X {
X(int) { std::cout << "int\n"; }
X() { std::cout << "default\n"; }
X& operator=(int) { std::cout << "assignment\n"; }
};
struct Foo {
X x;
Foo() { x = 5; } // prints: default\nassignment\n
// Where Foo() : x(5) {} // prints: int\n
};
At the language level both operations are completely different and cannot be transformed. That being said, the optimizer might be able to produce the exact same code for both if they are truly equivalent.
No, because the semantics are different. The following direct-initializes the member _o from o:
MyClass::MyClass (Obj o) : _o(o)
{}
On the other hand, the following default-initializes _o and then assigns the value of o to it:
MyClass::MyClass (Obj o)
{
_o = o;
}
In some cases there really might be no effective difference, such as if Obj is actually int. In cases where there is no effective difference, perhaps the compiler will generate the same code for both cases, but then again, maybe not. Depends how clever the optimizer is.
They are checking (if member variables needs to be created with parameters).
For example, this :
struct A {
A( int ) {}
};
struct B {
B(){ a = A(3); }
A a;
};
is going to fail with an error.
On the other hand, some types do not need parameters to be initialized. For example :
struct A
{
A(){
v = 3;
}
int v;
};
The standard doesn't require the compiler to issue a warning, but some compilers are capable of doing it (gcc has -Weffc++ flag).
Also, there are static code analysis tools to warn about such "errors".

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;
}