Dzyann
Dzyann

Reputation: 5208

Creating std::vector from list of arguments using Templates

I have a lot of C# Code that I have to write in C++. I don't have much experience in C++.

I am using Visual Studio 2012 to build. The project is an Static Library in C++ (not in C++/CLI).

I am sorry if this has been answered already, but I just couldn't find it.

In the C# code they would initialize a lot of arrays like this:

C#

double[] myArray = {10, 20, 30, 40};

Looking at how they were using arrays, when copying the code to C++ I decided to use std::vector to replace them. I would like to be able to initialize the vectors in the same way, because in the Unit Tests they use the arrays initialisation heavily, but I can't. I think in further versions of c++, vector supports it, but not in the one I have.

(Update)To make my previous statement more clear:

This doesn't work in VS2012:

vector<double> myVector{10, 20, 30, 40};

From this question I learned to create a vector from an array, so now I have a function like this:

C++

template<typename T, size_t N>
static std::vector<T> GetVectorFromArray( const T (&array)[N] )
{
    return std::vector<T>(array, array+N);
}

It works great, but now that means I have to create the array and then use my function:

C++ (I would like to avoid this, since the UnitTests have many arrays.)

double array[] = {1, 3, 5};
vector<double> myVector = ArrayUtils::GetVectorFromArray(array);

Is there a way I could make my function GetVectorFromArray receive a list of items, that I could later convert into a vector? My compiler doesn't support C++11

Upvotes: 0

Views: 894

Answers (3)

Mark Tolonen
Mark Tolonen

Reputation: 177705

You can simulate this behavior using the third-party C++ library, Boost:

#include <boost/assign.hpp>
#include <vector>
#include <iostream>

int main()
{
    std::vector<int> v = boost::assign::list_of(1)(2)(3)(4)(5);
    for(auto i : v)
        std::cout << i << std::endl;
}

You can also initialize a vector from an array using only the std library via non-member begin/end:

#include <boost/assign.hpp>
#include <vector>
#include <iostream>

int main()
{
    int array[] = {1,2,3,4,5,6,7,8,9,10};
    std::vector<int> v(std::begin(array),std::end(array));
    for(auto i : v)
        std::cout << i << std::endl;
}

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409176

You can't have "literal" arrays except when initializing an array in a declaration.

At least that was the case before C++11 standard, which allows things like what you want, but with an std::initializer_list argument:

template<typename T>
static std::vector<T> GetVectorFromArray( std::initializer_list<T> list )
{
    return std::vector<T>(list);
}

On the other hand, if your compiler support C++11 you can use it directly with the std::vector instead:

std::vector<int> myVector = { 1, 3, 5 };

Or even (with uniform initialization)

std::vector<int> myVector{ 1, 3, 5 };

Note: Unfortunately VS2012 doesn't support these things, so you either to use temporary arrays, or upgrade to a compiler which support it (like VS2013, or GCC, or Clang).


There are alternatives. One of them is the Boost assignment library (as answered by Mark Tolonen).

You can also use old C-style variable arguments. See e.g. this old question and its accepted answer for tips on how to do that. For this to work, you either need to provide the number of elements in the argument list as the first function argument, or provide a special sentinel to mark the end of the list. A warning though: As this is inherited straight from C, the extra type-safety provided by C++ doesn't exist. If you give an argument of the wrong type (say a double or a char) you might get undefined behavior.

The only other solution is to emulate e.g. the Boost assignment library, but that will require ridiculous amounts of code for such a simple thing.

Upvotes: 2

Xale
Xale

Reputation: 359

Visual studio 2012 does not support initializer list. You could use VS 2013 for support (or g++)

Upvotes: 0

Related Questions