3

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.

Steve Czetty
  • 6,147
  • 9
  • 39
  • 48
Dan
  • 2,625
  • 7
  • 39
  • 52
  • 1
    Take out the parentheses in the first, or just use the second, which is better, and it'll compile in C++11. As for partial classes, I don't know of anything :/ – chris Sep 05 '12 at 22:07
  • 2
    This is already possible in C++11. – Kerrek SB Sep 05 '12 at 22:08
  • Does Visual Studio 2010 compile C++ using the C++11 standard? Or is there a way to set that? I get an error in it now so I'm guessing it doesn't by default if it can at all. – Dan Sep 05 '12 at 22:10
  • @kerrek-sb - Uniform Initialization: http://en.wikipedia.org/wiki/C%2B%2B11#Uniform_initialization – Bob Fincheimer Sep 05 '12 at 22:10
  • In any case, adding new convenience functions is typically done by using free functions in C++ (because of the problems of inheritance). – eq- Sep 05 '12 at 22:10
  • @Dan MSVC++ does not support yet: [they call them initializer lists] http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx – Bob Fincheimer Sep 05 '12 at 22:10
  • @eq- So something like the static helper function would be the ideal way to go till Microsoft supports Initializer Lists? – Dan Sep 05 '12 at 22:13
  • @Dan, can't say about optimal. MSVC supports lambdas (IIRC) so they might be preferred for some cases, and static functions for others. – eq- Sep 05 '12 at 22:15
  • @eq- What would a lambda function look like in this case? I haven't used lambda functions in C++ before. – Dan Sep 05 '12 at 22:24
  • I should probably link to some answer with pretty formatting, but what the heck: a vector-returning lambda would look something like this (imagine the newlines): `auto lambda = []() -> vector { vector vec; /* add stuff, return vec; */ }`; of course you could also directly call the lambda instead of storing it in a variable. – eq- Sep 05 '12 at 22:32
  • @eq- I'm not seeing a way to get parameters with that lambda function should it be something like `auto lambda = [](T array[]) -> vector{ };` ? – Dan Sep 05 '12 at 22:48
  • @Dan, yes if you wanted to give it parameters (you wouldn't need if they were hard-coded). In that case, the lambda would be hardly simpler than your fourth option; there's no simple way to pass a function a range of strings without `initializer_list` support. – eq- Sep 05 '12 at 22:51
  • @eq- I'm noticing that but that's ok I just learned how to write a lambda so that's a win. Now how do I template a lambda function? I'm not sure where to put the `template `. – Dan Sep 05 '12 at 22:58
  • Unfortunately that's not possible. (SO recommends us to avoid extended discussions here, so further questions should perhaps be given a question of their own.) – eq- Sep 05 '12 at 23:01
  • I will end this by sharing a link to the answer to my question about templated Lambdas. [Here](http://stackoverflow.com/q/3575901/839501) Hope this helps anyone who bumps into these comments. – Dan Sep 05 '12 at 23:12

2 Answers2

7

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.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
MFH
  • 1,664
  • 3
  • 18
  • 38
5

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, i.e. 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);
Saurav Sahu
  • 13,038
  • 6
  • 64
  • 79
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380