Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize a C++ (11) std::vector with the content of another one and extra elements

I need an "elegant" way of initializing a vector in the declaration phase with the content of another one and a few extra elements.

What I want to solve is:

Let's consider the following (example) declaration with initialization:

const std::vector<std::string> c90_types = {
    "char",
    "signed char",
    "unsigned char",
    "short",
    "unsigned short",
    "int",
    "unsigned int",
    "long",
    "unsigned long",
    "float",
    "double",
    "long double"
};

const std::vector<std::string> c99_types = {
    "char",
    "signed char",
    "unsigned char",
    "short",
    "unsigned short",
    "int",
    "unsigned int",
    "long",
    "unsigned long",
    "float",
    "double",
    "long double",
    "long long",
    "unsigned long long",
    "intmax_t",
    "uintmax_t"
};

as you can see c99_types has a subset which is exactly c90_types. I want to avoid the situation where I need to change the subset and then change manually the "superset" too, just to avoid the extra step that might introduce bugs :)

As a side note, I don't want to write code like:

second.insert(second.begin(), first.begin(), first.end());
second.push_back(something);

Any good and clean solutions to this?

like image 355
Ferenc Deak Avatar asked Mar 10 '15 12:03

Ferenc Deak


People also ask

How do you initialize a vector to another vector?

Begin Initialize a vector v1 with its elements. Declare another vector v2 and copying elements of first vector to second vector using constructor method and they are deeply copied. Print the elements of v1. Print the elements of v2.

What is the correct way to initialize vector in C++? Mcq?

Begin Declare v of vector type. Call push_back() function to insert values into vector v. Print “Vector elements:”. for (int a : v) print all the elements of variable a.


2 Answers

There is a trick called "I want to initialize a const variable with something elaborate." that became possible with C++11, shamelessly stolen from Javascript.

const std::vector<std::string> c90_types = {
    "char",
    // and so on, and so forth....
};

const std::vector<std::string> c99_types = ([&](){
    const auto additional_types = { // initializer_list<const char *>, but it does not matter.
        "long long",
        "unsigned long long",
        "intmax_t",
        "uintmax_t"
    };

    std::vector<std::string> vec{c90_types};

    vec.insert(vec.end(), additional_types.begin(), additional_types.end());

    return vec;
})();

Pack your initialization logic into an unnamed lambda, and call it right away, copy-initializing your const variable.

vec is moved, not copied.

like image 165
Laurent LA RIZZA Avatar answered Nov 15 '22 17:11

Laurent LA RIZZA


You could define the biggest vector (here that would be c99_types) first, and then construct the others with iterators from the largest one.

Here is an example :

const vector<int> a{1,2,3,4};
const vector<int> b{begin(a), begin(a)+2}; // b is {1,2}

So you could write:

const std::vector<std::string> c99_types = {
    "char",
    "signed char",
    "unsigned char",
    "short",
    "unsigned short",
    "int",
    "unsigned int",
    "long",
    "unsigned long",
    "float",
    "double",
    "long double",
    "long long",
    "unsigned long long",
    "intmax_t",
    "uintmax_t"
};

const std::vector<std::string> c90_types{begin(c99_types), begin(c99_types)+12};
like image 24
tux3 Avatar answered Nov 15 '22 19:11

tux3