I want to initialize the sizes of vectors in an array of objects.
Every vector have the same size so...
LIB FILE:
#include <vector>
Class NameClass
{
public:
explicit NameClass( unsigned size )
{
vectorName.resize( size );
}
std::vector <type> vectorName;
};
MAIN FILE:
#include "lib.hpp"
int main( void )
{
NameClass object( size ); #1
NameClass object[ number_objects ]( size ); #2
NameClass object[ number_objects ] = {NameClass(size), NameClass(size), ... }; #3
return 0;
}
The #1 works, but is not an array, The #2 doesn't, compiler says "conversion from int to non-scalar type 'NameClass' requested" And #3 works, but... it's just absurd initialize every object. and I can't just put a static to size inside the class, because the value change.
So... My research say that I need use std::generate. the question is... Whats is the best way?
Sorry if is easy question how to use std::generate I'm beginner and get troubles to find the optimal solution.
Some people suggest complex solutions but, I keep using my solution
#include "lib.hpp"
int main( void )
{
unsigned number_objects = something;
unsigned size = other_thing;
NameClass object[ number_objects ];
for( unsigned i = 0; i < number_objects; i++)
object[i].vectorName.resize( size );
return 0;
}
I use thins because is really easy to understand , and works . But I'm open to other easy to understand and functional solutions.
If you are willing to use std::array
and C++14, we get:
template<std::size_t...Is>
auto index_over( std::index_sequence<Is...> ) {
return [](auto&&f)->decltype(auto) {
return decltype(f)(f)(std::integral_constant<std::size_t, Is>{}...);
};
}
template<std::size_t N>
auto index_upto( std::integral_constant<std::size_t, N> ={} ) {
return index_over( std::make_index_sequence<N>{} );
}
template<std::size_t N, class F,
class T = std::decay_t<std::result_of_t< F&( std::integral_constant<std::size_t, 0>& )>>,
class R = std::array<T, N>
>
R make_array( F&& f ) {
return index_upto<N>()( [&](auto...Is)->R {
return {{ f( Is )... }};
} );
}
we pass make_array<count>
a lambda. That lambda takes an argument convertible-from a compile-time std::size_t
whose value is I, and returns the Ith element of the array.
The result is a std::array
of size count
.
The lambda could take an auto I
to get the compile-time juiciness, or just std::size_t I
to get a runtime version of the value.
Most of the above can be translated into C++11, it just gets ugly. And I don't like ugly code.
Your code would look like:
int main( void )
{
unsigned size = 17;
constexpr std::size_t number_objects = 3;
auto objects = make_array<number_objects>( [&](std::size_t){ return NameClass(size); } );
}
and objects
is now a ( std::
) array of NameClass
of length number_objects
, all of size size
.
Create a default constructor for your class:
#include <vector>
class NameClass {
public:
NameClass() {} // default constructor
explicit NameClass( unsigned size ){
vectorName.resize( size );
}
std::vector <type> vectorName;
};
In main:
#include "lib.hpp"
int main( void )
{
unsigned number_objects = something;
unsigned size = other_thing;
NameClass object[ number_objects ];
for( unsigned i = 0; i < number_objects; i++)
object[i].vectorName.resize( size );
return 0;
}
The reason example 2 wasn't working is because C++ does not have a syntax for creating an array of objects for which a default constructor is not provided.
In python it would look something like:
[NameClass(size) for _ in range(number_objects)]
I digress.
To do without the default constructor and still create a list of, you can use this (question is why you would want to do this):
#include <iostream>
static constexpr unsigned NUM_OBJECTS = 10;
static constexpr unsigned VEC_SIZE = 30;
int main() {
NameClass *objects = static_cast<NameClass *>(operator new [](NUM_OBJECTS * sizeof *objects));
for (unsigned i = 0; i < NUM_OBJECTS; i++) {
objects[i].vectorName.resize(VEC_SIZE);
}
// Required to free memory
operator delete[](objects);
return 0;
}
If use vectors is not a problem, actually this works, and is really easy. It's a poem...
class-test.cpp
#include <stdio.h>
#include <algorithm>
#include "class.hpp"
int main( void )
{
std::vector <NameClass> object(number_objects, NameClass(size));
printf("%lu\n", object[0].vectorName.size() );
return 0;
}
class.hpp
#include <vector>
#include <algorithm>
#include <vector>
class NameClass {
public:
NameClass() {} // default constructor
explicit NameClass( unsigned size ){
vectorName.resize( size );
}
std::vector <double> vectorName;
};
And if you want use arrays then just use the default constructor.
clas.hpp
#include <vector>
class NameClass {
public:
NameClass(unsigned size) {
vectorName.resize( size );
} // default constructor
explicit NameClass( unsigned size ){ // eliminate this
vectorName.resize( size );
}
std::vector <type> vectorName;
};
class-test.cpp
#include <stdio.h>
#include "class.hpp"
int main() {
NameClass objects[2](4);
printf("%lu\n", objects[0].vectorName.size());
return 0;
}
this print a correct output.
You have to initialize every vector, it just how you present it in the code. you can do something this
std::vector<NameClass> classes(number_of_objects);
std::generate(classes.begin(), classes.end(), []{return NameClass(size);});
std::generate will initialize a instance of NameClass for each element of the vector.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.