To bypass this limitation, one can add a trivial constructor to
class A. The resuting code looks like the following:
class A {
public:
A() {};
A(const size_t & n) { ... };
}
const size_t m = 5;
const size_t n = 10;
A * t;
t = new A [n];
for (size_t i = 0; i < n; ++i)
t[i] = A(m);
I don't feel confortable with this solution: from my program
design it's non-sense to build an A object without specifying its
size...
Are there other solutions to the `array of objects from class
without default constructor' problem? Does my solution looks
horrible to C++ aesthetes?
Thanks for reading!
--
Matthias
I would allocate raw memory without any specific class first, then
call "placement new" operator with non-default constructors.
>
> Does my solution looks
> horrible to C++ aesthetes?
>
It is not horrible but you have unnecessary copying.
[code]
> I don't feel confortable with this solution: from my program design it's
> non-sense to build an A object without specifying its size...
> Are there other solutions to the `array of objects from class without
> default constructor' problem? Does my solution looks horrible to C++
> aesthetes?
(not a C++ expert, take everything below with a biiig grain of
salt)
Well, you could always decide to over-engineer and do something
like this (assuming you have control over the class interface):
#include <iostream>
#include <ostream>
class NextSizeCallback {
public: virtual int operator()() = 0; };
class IncCallback: public NextSizeCallback {
public: IncCallback(): n_(1) { }
virtual int operator()() { return n_++; }
private: int n_; };
class A {
public: static void setNextSizeCallback(
NextSizeCallback* c) { A::c_ = c; }
static int getNextSize() { return (*A::c_)(); }
A(): n_(getNextSize()) { }
int getSize() const { return n_; }
private: static NextSizeCallback* c_;
int n_; };
NextSizeCallback* A::c_ = NULL;
int main() {
IncCallback i;
A::setNextSizeCallback(&i);
A* t = new A[10];
for (int i = 0; i != 10; ++i)
std::cout << t[i].getSize() << std::endl;
return 0; }
I doubt this is any better in terms of readability and
maintainability than using placement new and creating your
objects explicitly, though.
--
Waterfall: One Process To Rule Them All
Use a std::vector<A> and its push_back function. A vector's value
type only needs to be copy-constructible. push_back will copy-
construct the new element in the vector.
Altough this is not of help for you now it's IMHO still worth
mentioning: The future C++ version will replace the "copy
constructible" requirement with a "move constructible" requirement for
the value type. Also, it will be possible to directly create such an
object in the vector via std::vector::emplace_back à la
std::vector<A> avec;
avec.emplace_back(5);
Side note: Consider making A::A(size_t) an explicit constructor.
Cheers!
SG
It may not be trivial, but it isn't very hard either. STL data
containers use this kind of technique all the time. (How do you think
their reserve() function works?)
What you do is that instead of using new, you allocate space using
::operator new (which does not initialize the allocated memory and
returns a void*), and then you initialize this allocated memory with
placement new. This is a bit low-level programming (and slightly
error-prone), but not very difficult.
I've finaly decided to pre-allocate storage without initialization
(a call to ::operator new, followed by static_cast) then
initialize individual elements with a placement new.
Yes, Juha, this wasn't difficult! The syntax is not easily found,
but the result is quite readable.
Thanks a lot!
--
Matthias