Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable brace enclosed initializer lists for my own collection class?

Given this example class:

template<typename T>
class ExampleContainer
{
private:        
  std::map<T, int> _objects;
  int _sum;

public:
  ExampleContainer()
    : _objects(), _sum(0)
  {
  }

  void Add(T obj, int add)
  {
    _objects[obj] = add; // yes this is bad, but it's an example.
    _sum += add;
  }
};

What is needed to be able to use it like this:

ExampleContainer<char*> _rarities =
{
  { "One", 600 },
  { "Two", 200 },
  { "Three", 50 },
  { "Four", 10 },
  { "Five", 1 },
};

I know it must be somehow possible, because I can initialize a std::map like that already.

Thanks in advance for any answers.

like image 262
xNidhogg Avatar asked Dec 21 '22 09:12

xNidhogg


1 Answers

Just add a constructor accepting an std::initializer_list to your ExampleContainer class:

ExampleContainer(std::initializer_list<typename std::map<T, int>::value_type> l)
    :
    _objects(l)
{
}

This will be invoked every time you use the curly braces to initialize the object, as in this case:

ExampleContainer<char*> _rarities =
{
    ...
};

This way, each entry within the curly braces will become an element of the initializer list.

Since the underlying type of the initializer list here is std::map<T, int>::value_type, temporary objects of that type will be constructed from the values you provide:

ExampleContainer<char*> _rarities =
{
    { "One", 600 },     // Each of these entires will cause the creation of
    { "Two", 200 },     // a temporary object of type:
    { "Three", 50 },    //     std::pair<char* const, int>
    { "Four", 10 },     // that will become an element of the initializer
    { "Five", 1 },      // list received by the constructor.
};

Also note, that the conversion from a string literal to char* is deprecated in C++03 and invalid in C++11 (string literals have type char const[] in C++11). Thus, you may want to give your variable _rarities the type ExampleContainer<char const*> instead (C array types decay to pointer types).

UPDATE:

As correctly pointed out by @LightnessRacesInOrbit in the comments, this approach is dangerous in case you are not going to use just string literals in your container (that's something I kind of assumed from your example, but in fact nothing implies it). It is a better idea to use std::string instead (so you should declare _rarities as ExampleContainer<std::string>).

like image 50
Andy Prowl Avatar answered Dec 24 '22 02:12

Andy Prowl