Vector initialisation

May 25, 2011

Oftentimes while doing this crazy business we refer to as “programming”, I find myself with the want to create lists of stuff. Not just any lists of stuff though, lists that I can set in code that never needs to change. A static array of stuff, if you will.

Luckily, I live in the day and age where C++ happens to be backwards-compatible with C, which has a way of setting an array to just such a list of stuff: static array initialisation.

int array[] = 
{
	1,
	2,
	3,
	4,
	56,
};

And that’s all well and good if what I want to use is an array of stuff. But what if what I really want to use is a solution grounded in the standard C++ libraries? What if I want to have a vector that starts out with certain contents that I can then manipulate as my twisted and purile mind sees fit? What if I wanted to use C++ classes that were more than just structs or Plain Old Data Structures (PODS)? Why, then I would need a way to initialise a vector! What’s that? There isn’t one?

 

Okay, I speak too soon. C++ 0x has/will have one. I never know whether to speak in the future or present tense with that one, as it’s technically not really ratified yet but a lot of people are getting sick of waiting. Anyways, with C++ more-shiny-version the syntax is simple and delicious:

 

//declare a class that takes an initializer list in a constructor
class ShinyClass
{
public:
	ShinyClass(std::initializer_list<int> list);
};

//use the list
void main()
{
	ShinyClass array = 
	{
		1,
		2,
		3,
		44,
		56,
	};
}

 

 

However, for those poor souls who, like myself, are stuck with the version of C++ that actually has an official standard and universal compiler support, this snippet is nothing more than a tease. Generally, the closest we can get is to first initialise an array and then copy the contents in to a vector like so:

const int array[] = {1, 2, 33, 46, 55};
const std::vector<const int> vec(array, array+sizeof(array)*sizeof(int) );

This is quick, but it doesn’t really work with anything that isn’t a struct or a PODS, and doesn’t play all that nice with constructors. There’s a Boost alternative, Boost.Assign, that can be used for initializing vectors. Frankly though, Boost just adds so much compile time and bloat to anything that uses it that I’m not even going to show a snippet of it. Feel free to look it up yourself if you’re interested.

 

The final solution is one which I rolled myself after seeing a similar (but more evil one) on a Stack Overflow question.

template <typename T>
class vector_init
{
public:
    vector_init(const T& val)
    {
        vec.push_back(val);
    }
    inline vector_init& operator()(T val)
    {
        vec.push_back(val);
        return *this;
    }
    inline std::vector<T> end()
    {
        return vec;
    }
private:
    std::vector<T> vec;
};

 

Use it like so:

std::vector<int> testVec = vector_init<int>(1)(2)(3)(4)(5).end();

It won’t relieve all your initialization worries, but it will certainly help with calling classes with specific C++ functions and filling vectors with pre-calculated content. Enjoy!

Posted by | Categories: Blog |

Share with others

No Responses so far | Have Your Say!

Leave a Feedback

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Current month ye@r day *