Slazer
Slazer

Reputation: 4990

Initialize a container that is a private member variable of a class

I have a list<string> myList as a private attribute of my class. The content of this list is known at compile time and is constant. Is there any compact way (in C++03) to initialize its value? I can only think of this:

MyClass::MyClass(){
myList.push_back(string("str1"));
myList.push_back(string("str2"));
myList.push_back(string("str3"));
etc.
}

I would like something like this:

MyClass::MyClass():list("str1","str2","str3",etc.){
}

Upvotes: 2

Views: 1132

Answers (2)

John Dibling
John Dibling

Reputation: 101446

I tend do do something like this:

static const string my_strs[] =
{
  "str1",
  "str2",
  "str3"
};

static const num_my_strs = sizeof(my_strs)/sizeof(my_strs[0]);

Then when it comes time to initialize the list:

MyClass::MyClass()
:  myList(my_strs, my_strs + num_my_strs)
{
}

...or:

MyClass::MyClass()
{
  copy( my_strs, my_strs+num_my_strs, back_inserter(myList));
}

There are pros and cons to this approach. The obvious con is you now have 2 copies of your data. This also raises the question, if you know the contents at compile-time and they never change, do you even need the list at all? Why not just use the static const array?

On the pro side, the code to initialize the list is a 1-liner, and never needs to change even if you change the compile-time constant data that's being coped in to the list.

Edit: You can use standard library algorithms like find with plain old C-style arrays. For example:

const string* it = std::find(my_strs, my_strs+num_my_strs, "str1");
if( it == (my_strs+num_my_strs) ) // functionally same as 'list.end()' eg, item not found
{ 
  // not found
}
else
{
  // found -- it points to item found
  string found_item = *it;
}

Edit2 Whether or not an expression like int a[2]; &a[2]; is well-defined is being debated. I have edited the pointer math above to use a method that is well-known to not evoke UB.

Edit3 I've found the relevant passages in the Standard relating to this. The above expression (int a[2]; &a[2];) is in fact Undefined Behavior. I have already edited my answer to not use that method. Thanks to @MooingDuck for bringing this up.

Upvotes: 4

Bob Fincheimer
Bob Fincheimer

Reputation: 18036

This code is not fully tested, but I would suggest this if you can't use the new and cool stuff in C++11:

class MyClassCreator
{
    MyClass result;
public:
    MyClassCreator(std::string param)
    {
        result.myList.push_back(param);
    }

    MyClassCreator& operator()(std::string param)
    {
        result.myList.push_back(param); 
        return *this;
    }

    operator MyClass() { return result; }

};

Usage:

MyClass c = MyClassCreator("object1")("object2")("object3");

EDIT

See full example at http://ideone.com/LWGRCc

Upvotes: 3

Related Questions