简体   繁体   中英

How to add an Initializer List constructor to STL vector

So what I want to do is extend the existing vector class in my program to allow me to say this,

vector<string>* vec = new vector<string>(){"Value1","Value2"};

or

vector<string>* vec = new vector<string>({"Value1","Value2"});

or

vector<string> vec = {"Value1","Value2"};

I know I can accomplish something like this but doing this,

string temp[] = {"Value1","Value2"};
vector<string> vec(temp, temp+ sizeof(temp) /  sizeof( temp[0] ) ); 

This uses the vectors iterator constructor but can't I remove the extra line?

I know in C# you can add whatever you want to existing things by using the partial key word like this,

public partial class ClassName
{
   ClassName(Stuff stuff)
   {

   }
   void AmazingNewMethod()
   {

   }    
}

Does C++ have a nifty trick like this somewhere?

Do I have to inherit vector and build a customVector that has a constructor that behind the scenes does the iterator constructor thing?

Maybe wrap those lines in a static Helper Function call that sets it by Reference and add it to a toolbox class somewhere?

I feel like lots of programmers have hit this problem. Are there any elegant solutions out there?

Thanks.

Edit: fixed the title to mention this is an Initializer List constructor.

In C++11 there would be initializer lists to suite this approach. As you're mentioning .NET I now assume that you're using MS Visual Studio. Microsoft does NOT implement initializer lists, therefore the easiest way to accomplish something like that would be a function that returns the vector with all the elements added.

On the partial thing: C++ does not offer a feature in the same vein as .NET's partial classes.

The C++ 2011 way is to accept an std::initializer_list<T> as a constructor argument:

#include <initializer_list>

template <typename T>
class foo {
    T *d_array;
public:
    foo(std::initializer_list<T> list)
        : d_array(new T[list.size()]) {
        std::copy(list.begin(), list.end(), this->d_array);
    }
    foo(foo const&);
    foo& operator= (foo const&);
    ~foo() { delete[] this->d_array; }
};

The above clearly only concentrates on how use an std::initializer_list<T> . To actually do the allocation internally you'd allocate raw memory and construct the object in-place. However, this wasn't what the question is about.

With respect to adding this support to std::vector<T> : you don't have to! In C++ 2011 std::vector<T> can be initialized with an std::initializer_list<T> . In C++ 2003 you can't do this. The best you could do is to support construction from an array, using a constructor looking something like this:

template <typename T>
    template <typename S, int Size>
foo<T>::foo(S const (&array)[Size])
    d_array(new T[Size]) {
    std::copy(array, array + Size, d_array);
};

However, there is no way to extend an existing without changing its type. To avoid reimplementing most of the members you could publically inherit from the type you want to extend and add all required constructors (these are not inherited; in C++ 2011 you could inherit the existing constructors but then, with C++ 2011 you wouldn't need to do any of this anyway).

An alternative you might want to use with C++ 2003 is to create a factor function taking a built-in array, ie something like this:

template <typename T, typename S, int Size>
std::vector<T>
make_vector(S const (&array)[Size]) {
    return std::vector<T>(array, array + Size);
}

char const* init[] = { "Hello", "World" };
std::vector<std::string> value = make_vector<std::string>(init);

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM