C++ initialize const static vector dynamically - c++

I would like to initalize a static const std::vector in class Foo to {0, 1, 2, 3, ..., n} where n is known at compile time based on the value of Last in the enum below. The goal is for Foo::all to contain all the values of the Fruit enum.
In foo.h:
enum Fruit { Apple, Orange, Banana, ..., Last };
class Foo {
public:
static const vector<int> all;
};
In foo.cpp:
// initialization of Foo::all goes here.

As a third option:
namespace {
std::vector<int> create();
}
const std::vector<int> Foo::all = create();
And create() can do anything it likes, even using push_back() for each element, because the vector it creates isn't const.
Or you could make create() a constexpr function using <index_tuple.h>
#include <redi/index_tuple.h>
namespace {
template<unsigned... I>
constexpr std::initializer_list<int>
create(redi::index_tuple<I...>)
{
return { I... };
}
}
const std::vector<int> Foo::all = create(typename redi::make_index_tuple<Last>::type());

You can use boost::irange:
auto range = boost::irange(0, n + 1);
const vector<int> Foo::numbers(range.begin(), range.end());

If your n is small enough and you use a compiler, which supports c++0x or c++11, just spell it out
const std::vector<int> Foo::all{0, 1, 2, 3, ..., n};
Fixed as per #Jonathan's explanation.

Related

Initialize an array of template structures

The following snippet of code simply creates a structure that has three members. One of them is a callback function. I would like to initialize an array of these structures but I don't know the syntax, where I can have multiple callbacks with varying prototypes.
#include <iostream>
#include <functional>
template <typename Func>
struct Foo
{
Foo(int a, int b, Func func):
_a{a},
_b{b},
_func{func}{}
int _a;
int _b;
Func _func;
};
int main() {
auto test = [](){std::cout << "hello\n";};
Foo<std::function<void(void)>> foo(5,10, test);
foo._func();
//array version
//......................
}
How about this
//array version
Foo<std::function<void(void)>> a[] = { {5, 10, test}, {1, 2, test} };
Depending on what "array" you want to use, I think the creation is straight-forward, here with std::vector. You can use any container you like. Accessing here done with [], but could also be done with the at() method
typedef Foo<std::function<void(void)>> FooTypeDef;
int main() {
auto test = [](){std::cout << "hello\n";};
FooTypeDef foo(5,10, test);
foo._func();
//array version
//......................
std::vector<FooTypeDef> array;
array.push_back(foo);
array.push_back(foo);
array[0]._func();
array[1]._func();
}
And maybe use a typedef ;)

Using `constexpr` with array initialization

I know that in C++11, I can write
class foo {
static constexpr const char *one = "one";
}
However, when I try to do the same for an array
class bar {
static constexpr const float prim[4] = {2, 3, 5, 7};
}
(and reference it later on) I get an undefined reference linker error.
Is this just not possible for arrays or am I missing something in the syntax?
Static constexpr data member declarations aren't definitions in C++11/14, therefore you cannot odr-use prim.
To work around it, put the following statement somewhere in your cpp file as you would do with any other non-constexpr static data member:
constexpr const float bar::prim[4];
In other terms, this returns an undefined reference:
struct bar {
static constexpr const float prim[4] = {2, 3, 5, 7};
};
int main() {
auto *foo = bar::prim;
}
This doesn't:
struct bar {
static constexpr const float prim[4] = {2, 3, 5, 7};
};
constexpr const float bar::prim[4];
int main() {
auto *foo = bar::prim;
}
Because in the second case you are actually defining prim other than declaring it and thus you can get its address, use it by means of a reference, and so on...

Returning reference to an array of specific size without explicitly stating the size in return type

I've got the following function:
... getX()
{
static int x[] = {1, 2, 3};
return x;
}
I'd like to have its return type as int(&)[3] but don't wan't to specify the size (3) explicitly.
How do I do that?
(Please don't ask why I want that.)
UPD
Well, OK, I need to pass a result to a template function taking int(&x)[N] as a parameter (and I don't want to pass the size explicitly to that template function), so I don't see how a solution with returning a pair could work...
In C++14:
auto& getX()
{
static int x[] = {1, 2, 3};
return x;
}
Also, consider using std::array instead of C-style arrays.
I cannot currently think of any Standard-compliant C++11 solution. Here's one using compound literals, assuming that your goal is to not repeat the elements and to deduce a reference-to-array:
#include <type_traits>
#define ITEMS 1, 2, 3
auto getX() -> decltype((int[]){ITEMS})
{
static int x[] = {ITEMS};
return x;
}
#undef ITEMS
int main()
{
static_assert(std::is_same<decltype(getX()), int(&)[3]>{});
}
Do you need the size available as a compile-time constant? I would suggest using gsl::span (or roll your own). This is basically just a pointer and a size, that satisfies the range concept:
gsl::span<int> getX()
{
static int x[] = {1, 2, 3};
return x;
}
C++11
Another C++11 alternative (workaround), in case your theoretical scenario (not asking why ...) allows wrapping the static array as a (literal) static data member of an otherwise stateless type:
class Foo
{
static constexpr int x[] = {1, 2, 3};
// delete ctor(s) ...
public:
static auto getX() -> std::add_lvalue_reference<decltype(x)>::type { return x; }
};
constexpr int Foo::x[];
Or, e.g.
class Foo
{
template <typename T, std::size_t n>
static constexpr std::size_t array_size(const T (&)[n]) { return n; }
static constexpr int x[] = {1, 2, 3};
// delete ctor(s) ...
public:
template<std::size_t N = array_size(x)>
static const int (&getX())[N] { return x; }
};
constexpr int Foo::x[];
Any of the two above applied in the use case you describe in your question:
template <std::size_t N>
void feedX(const int (&x)[N])
{
for (const auto num: x) { std::cout << num << "\n"; }
}
int main()
{
feedX(Foo::getX()); /* 1
2
3 */
}
This wouldn't help you in case your theoretical scenario would need to mutate the static data, though. You could tweak the above into a mutating-allowing scenario, but at the cost of having to specify the size of x at its declaration, as it can no longer be (constant-)initialized and size-deduced at that point, and I believe this size explicitness is what you wanted to avoid in the first place. Anyway, for completeness:
class Foo
{
static int x[3];
public:
static auto getX() -> std::add_lvalue_reference<decltype(x)>::type { return x; }
};
int Foo::x[] = {1, 2, 3};
template <std::size_t N>
void feedAndMutateX(int (&x)[N])
{
for (auto& num: x) { std::cout << num++ << "\n"; }
}
int main()
{
feedAndMutateX(Foo::getX()); /* 1
2
3 */
feedAndMutateX(Foo::getX()); /* 2
3
4 */
}
If you really want a reference, and have C++14, then decltype(auto) with a parenthesized id expression:
decltype(auto) get_arr() {
static int x[] = {1, 2 ,3};
return (x);
}
Will deduce as a reference to the array of that size. See it live, where the type of the reference is shown in the error message.

Use STL std::sort the way as qsort_r

With qsort_r, we can use external parameters in the compare function. For instance,
int cmp_with_parameter(void *a, void *b, void *p)
{
return (int*)p[*(int*)a] - (int*)p[*(int*b)];
}
int main() {
int values[] = {1,2,3,4};
int arr[] = {0, 1, 2, 3};
qsort_r(arr, 4, sizeof(arr[0]), cmp_with_parameter, values);
}
We can sort int arr[] by the value in values[].
Now, I would like to implement the similar function with std::sort, that is how I can use external values in std::sort? Thank you in advance.
The comparison function taken by std::sort() can be a function object holding suitable information. For example:
std::sort(std::begin(arr), std::end(arr),
[=](int a, int b){ return values[a] < values[b]; });
You need to create a functor as your comparator. A common way to make a functor is using a struct with the call operator overloaded:
struct cmp_with_parameter
{
const int* values; // keep a pointer to the external array
cmp_with_parameter(const int* values): values(values) {}
// overloading this operator allows an object
// of this struct to be called like a function.
bool operator()(int a, int b) const
{
return values[a] < values[b];
}
};
int main()
{
int values[] = { 1, 2, 3, 4 };
int arr[] = { 0, 1, 2, 3 };
std::sort(arr, arr + sizeof(arr)/sizeof(arr[0]), cmp_with_parameter(values));
// ...
}
If you compiler supports C++11 you can simplify the std::sort() parameters:
int main()
{
int values[] = { 1, 2, 3, 4 };
int arr[] = { 0, 1, 2, 3 };
std::sort(std::begin(arr), std::end(arr), cmp_with_parameter(values));
// ...
}
Wikipedia has a good example of how to address this issue: Function Object:C/C++

What is the easiest way to initialize a std::vector with hardcoded elements?

I can create an array and initialize it like this:
int a[] = {10, 20, 30};
How do I create a std::vector and initialize it similarly elegant?
The best way I know is:
std::vector<int> ints;
ints.push_back(10);
ints.push_back(20);
ints.push_back(30);
Is there a better way?
If your compiler supports C++11, you can simply do:
std::vector<int> v = {1, 2, 3, 4};
This is available in GCC as of version 4.4. Unfortunately, VC++ 2010 seems to be lagging behind in this respect.
Alternatively, the Boost.Assign library uses non-macro magic to allow the following:
#include <boost/assign/list_of.hpp>
...
std::vector<int> v = boost::assign::list_of(1)(2)(3)(4);
Or:
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
...
std::vector<int> v;
v += 1, 2, 3, 4;
But keep in mind that this has some overhead (basically, list_of constructs a std::deque under the hood) so for performance-critical code you'd be better off doing as Yacoby says.
One method would be to use the array to initialize the vector
static const int arr[] = {16,2,77,29};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
If you can, use the modern C++[11,14,17,20,...] way:
std::vector<int> ints = {10, 20, 30};
The old way of looping over a variable-length array or using sizeof() is truly terrible on the eyes and completely unnecessary in terms of mental overhead. Yuck.
In C++0x you will be able to do it in the same way that you did with an array, but not in the current standard.
With only language support you can use:
int tmp[] = { 10, 20, 30 };
std::vector<int> v( tmp, tmp+3 ); // use some utility to avoid hardcoding the size here
If you can add other libraries you could try boost::assignment:
vector<int> v = list_of(10)(20)(30);
To avoid hardcoding the size of an array:
// option 1, typesafe, not a compile time constant
template <typename T, std::size_t N>
inline std::size_t size_of_array( T (&)[N] ) {
return N;
}
// option 2, not typesafe, compile time constant
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
// option 3, typesafe, compile time constant
template <typename T, std::size_t N>
char (&sizeof_array( T(&)[N] ))[N]; // declared, undefined
#define ARRAY_SIZE(x) sizeof(sizeof_array(x))
In C++11:
#include <vector>
using std::vector;
...
vector<int> vec1 { 10, 20, 30 };
// or
vector<int> vec2 = { 10, 20, 30 };
Using Boost list_of:
#include <vector>
#include <boost/assign/list_of.hpp>
using std::vector;
...
vector<int> vec = boost::assign::list_of(10)(20)(30);
Using Boost assign:
#include <vector>
#include <boost/assign/std/vector.hpp>
using std::vector;
...
vector<int> vec;
vec += 10, 20, 30;
Conventional STL:
#include <vector>
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
Conventional STL with generic macros:
#include <vector>
#define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0])
#define ARRAY_END(ar) (ar + ARRAY_SIZE(ar))
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec (arr, ARRAY_END(arr));
Conventional STL with a vector initializer macro:
#include <vector>
#define INIT_FROM_ARRAY(ar) (ar, ar + sizeof(ar) / sizeof(ar[0])
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec INIT_FROM_ARRAY(arr);
I tend to declare
template< typename T, size_t N >
std::vector<T> makeVector( const T (&data)[N] )
{
return std::vector<T>(data, data+N);
}
in a utility header somewhere and then all that's required is:
const double values[] = { 2.0, 1.0, 42.0, -7 };
std::vector<double> array = makeVector(values);
Before C++ 11:
Method 1
vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
Method 2
vector<int>v;
v.push_back(SomeValue);
C++ 11 onward below is also possible
vector<int>v = {1, 3, 5, 7};
We can do this as well
vector<int>v {1, 3, 5, 7}; // Notice .. no "=" sign
For C++ 17 onwards we can omit the type
vector v = {1, 3, 5, 7};
Starting with:
int a[] = {10, 20, 30}; //I'm assuming 'a' is just a placeholder
If you don't have a C++11 compiler and you don't want to use Boost:
const int a[] = {10, 20, 30};
const std::vector<int> ints(a, a+sizeof(a)/sizeof(int)); //Make it const if you can
If you don't have a C++11 compiler and can use Boost:
#include <boost/assign.hpp>
const std::vector<int> ints = boost::assign::list_of(10)(20)(30);
If you do have a C++11 compiler:
const std::vector<int> ints = {10,20,30};
For vector initialisation -
vector<int> v = {10, 20, 30}
can be done if you have a C++11 compiler.
Else, you can have an array of the data and then use a for loop.
int array[] = {10,20,30}
for(unsigned int i=0; i<sizeof(array)/sizeof(array[0]); i++)
{
v.push_back(array[i]);
}
Apart from these, there are various other ways described in previous answers using some code. In my opinion, these ways are easy to remember and quick to write.
The easiest way to do it is:
vector<int> ints = {10, 20, 30};
If your compiler supports Variadic macros (which is true for most modern compilers), then you can use the following macro to turn vector initialization into a one-liner:
#define INIT_VECTOR(type, name, ...) \
static const type name##_a[] = __VA_ARGS__; \
vector<type> name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))
With this macro, you can define an initialized vector with code like this:
INIT_VECTOR(int, my_vector, {1, 2, 3, 4});
This would create a new vector of ints named my_vector with the elements 1, 2, 3, 4.
I build my own solution using va_arg. This solution is C++98 compliant.
#include <cstdarg>
#include <iostream>
#include <vector>
template <typename T>
std::vector<T> initVector (int len, ...)
{
std::vector<T> v;
va_list vl;
va_start(vl, len);
for (int i = 0; i < len; ++i)
v.push_back(va_arg(vl, T));
va_end(vl);
return v;
}
int main ()
{
std::vector<int> v = initVector<int> (7,702,422,631,834,892,104,772);
for (std::vector<int>::const_iterator it = v.begin() ; it != v.end(); ++it)
std::cout << *it << std::endl;
return 0;
}
Demo
If you don't want to use Boost, but want to enjoy syntax like
std::vector<int> v;
v+=1,2,3,4,5;
just include this chunk of code
template <class T> class vector_inserter{
public:
std::vector<T>& v;
vector_inserter(std::vector<T>& v):v(v){}
vector_inserter& operator,(const T& val){v.push_back(val);return *this;}
};
template <class T> vector_inserter<T> operator+=(std::vector<T>& v,const T& x){
return vector_inserter<T>(v),x;
}
In C++11:
static const int a[] = {10, 20, 30};
vector<int> vec (begin(a), end(a));
A more recent duplicate question has this answer by Viktor Sehr. For me, it is compact, visually appealing (looks like you are 'shoving' the values in), doesn't require C++11 or a third-party module, and avoids using an extra (written) variable. Below is how I am using it with a few changes. I may switch to extending the function of vector and/or va_arg in the future instead.
// Based on answer by "Viktor Sehr" on Stack Overflow
// https://stackoverflow.com/a/8907356
//
template <typename T>
class mkvec {
public:
typedef mkvec<T> my_type;
my_type& operator<< (const T& val) {
data_.push_back(val);
return *this;
}
my_type& operator<< (const std::vector<T>& inVector) {
this->data_.reserve(this->data_.size() + inVector.size());
this->data_.insert(this->data_.end(), inVector.begin(), inVector.end());
return *this;
}
operator std::vector<T>() const {
return data_;
}
private:
std::vector<T> data_;
};
std::vector<int32_t> vec1;
std::vector<int32_t> vec2;
vec1 = mkvec<int32_t>() << 5 << 8 << 19 << 79;
// vec1 = (5, 8, 19, 79)
vec2 = mkvec<int32_t>() << 1 << 2 << 3 << vec1 << 10 << 11 << 12;
// vec2 = (1, 2, 3, 5, 8, 19, 79, 10, 11, 12)
You can do that using boost::assign:
vector<int> values;
values += 1,2,3,4,5,6,7,8,9;
Details are here.
The below methods can be used to initialize the vector in C++.
int arr[] = {1, 3, 5, 6}; vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
vector<int>v; v.push_back(1); v.push_back(2); v.push_back(3); and so on
vector<int>v = {1, 3, 5, 7};
The third one is allowed only in C++11 onwards.
There are a lot of good answers here, but since I independently arrived at my own before reading this, I figured I'd toss mine up here anyway...
Here's a method that I'm using for this which will work universally across compilers and platforms:
Create a struct or class as a container for your collection of objects. Define an operator overload function for <<.
class MyObject;
struct MyObjectList
{
std::list<MyObject> objects;
MyObjectList& operator<<( const MyObject o )
{
objects.push_back( o );
return *this;
}
};
You can create functions which take your struct as a parameter, e.g.:
someFunc( MyObjectList &objects );
Then, you can call that function, like this:
someFunc( MyObjectList() << MyObject(1) << MyObject(2) << MyObject(3) );
That way, you can build and pass a dynamically sized collection of objects to a function in one single clean line!
If you want something on the same general order as Boost::assign without creating a dependency on Boost, the following is at least vaguely similar:
template<class T>
class make_vector {
std::vector<T> data;
public:
make_vector(T const &val) {
data.push_back(val);
}
make_vector<T> &operator,(T const &t) {
data.push_back(t);
return *this;
}
operator std::vector<T>() { return data; }
};
template<class T>
make_vector<T> makeVect(T const &t) {
return make_vector<T>(t);
}
While I wish the syntax for using it was cleaner, it's still not particularly awful:
std::vector<int> x = (makeVect(1), 2, 3, 4);
typedef std::vector<int> arr;
arr a {10, 20, 30}; // This would be how you initialize while defining
To compile use:
clang++ -std=c++11 -stdlib=libc++ <filename.cpp>
// Before C++11
// I used following methods:
// 1.
int A[] = {10, 20, 30}; // original array A
unsigned sizeOfA = sizeof(A)/sizeof(A[0]); // calculate the number of elements
// declare vector vArrayA,
std::vector<int> vArrayA(sizeOfA); // make room for all
// array A integers
// and initialize them to 0
for(unsigned i=0; i<sizeOfA; i++)
vArrayA[i] = A[i]; // initialize vector vArrayA
//2.
int B[] = {40, 50, 60, 70}; // original array B
std::vector<int> vArrayB; // declare vector vArrayB
for (unsigned i=0; i<sizeof(B)/sizeof(B[0]); i++)
vArrayB.push_back(B[i]); // initialize vArrayB
//3.
int C[] = {1, 2, 3, 4}; // original array C
std::vector<int> vArrayC; // create an empty vector vArrayC
vArrayC.resize(sizeof(C)/sizeof(C[0])); // enlarging the number of
// contained elements
for (unsigned i=0; i<sizeof(C)/sizeof(C[0]); i++)
vArrayC.at(i) = C[i]; // initialize vArrayC
// A Note:
// Above methods will work well for complex arrays
// with structures as its elements.
It is pretty convenient to create a vector inline without defining variable when writing test, for example:
assert(MyFunction() == std::vector<int>{1, 3, 4}); // <- this.
"How do I create an STL vector and initialize it like the above? What is the best way to do so with the minimum typing effort?"
The easiest way to initialize a vector as you've initialized your built-in array is using an initializer list which was introduced in C++11.
// Initializing a vector that holds 2 elements of type int.
Initializing:
std::vector<int> ivec = {10, 20};
// The push_back function is more of a form of assignment with the exception of course
//that it doesn't obliterate the value of the object it's being called on.
Assigning
ivec.push_back(30);
ivec is 3 elements in size after Assigning (labeled statement) is executed.
There are various ways to hardcode a vector. I will share few ways:
Initializing by pushing values one by one
// Create an empty vector
vector<int> vect;
vect.push_back(10);
vect.push_back(20);
vect.push_back(30);
Initializing like arrays
vector<int> vect{ 10, 20, 30 };
Initializing from an array
int arr[] = { 10, 20, 30 };
int n = sizeof(arr) / sizeof(arr[0]);
vector<int> vect(arr, arr + n);
Initializing from another vector
vector<int> vect1{ 10, 20, 30 };
vector<int> vect2(vect1.begin(), vect1.end());
If the array is:
int arr[] = {1, 2, 3};
int len = (sizeof(arr)/sizeof(arr[0])); // finding length of array
vector < int > v;
v.assign(arr, arr+len); // assigning elements from array to vector
Related, you can use the following if you want to have a vector completely ready to go in a quick statement (e.g. immediately passing to another function):
#define VECTOR(first,...) \
([](){ \
static const decltype(first) arr[] = { first,__VA_ARGS__ }; \
std::vector<decltype(first)> ret(arr, arr + sizeof(arr) / sizeof(*arr)); \
return ret;})()
example function
template<typename T>
void test(std::vector<T>& values)
{
for(T value : values)
std::cout<<value<<std::endl;
}
example use
test(VECTOR(1.2f,2,3,4,5,6));
though be careful about the decltype, make sure the first value is clearly what you want.
B. Stroustrup describes a nice way to chain operations in 16.2.10 Selfreference on page 464 in the C++11 edition of the Prog. Lang. where a function returns a reference, here modified to a vector. This way you can chain like v.pb(1).pb(2).pb(3); but may be too much work for such small gains.
#include <iostream>
#include <vector>
template<typename T>
class chain
{
private:
std::vector<T> _v;
public:
chain& pb(T a) {
_v.push_back(a);
return *this;
};
std::vector<T> get() { return _v; };
};
using namespace std;
int main(int argc, char const *argv[])
{
chain<int> v{};
v.pb(1).pb(2).pb(3);
for (auto& i : v.get()) {
cout << i << endl;
}
return 0;
}
1
2
3
The simplest, ergonomic way (with C++ 11 or later):
auto my_ints = {1,2,3};
In case you want to have it in your own class:
#include <initializer_list>
Vector<Type>::Vector(std::initializer_list<Type> init_list) : _size(init_list.size()),
_capacity(_size),
_data(new Type[_size])
{
int idx = 0;
for (auto it = init_list.begin(); it != init_list.end(); ++it)
_data[idx++] = *it;
}