0

So I tried yesterday to start using std::initializer_list but that wasn't a huge success. There is one of my last try:

#include <unordered_map>
#include <string>

     struct XmlState {

        using U_StateFunc = std::function<void()>;
        using U_MapStateFunc = std::unordered_map<std::string, U_StateFunc>;

        U_StateFunc     beforeProcess;
        U_StateFunc     afterProcess;
        U_MapStateFunc  funcMap;

        XmlState
          (U_StateFunc&& bProcess,
           U_StateFunc&& aProcess,
           std::initializer_list<typename U_MapStateFunc::value_type> mapParams)
          : beforeProcess(std::move(bProcess)),
            afterProcess(std::move(aProcess)),
            funcMap(mapParams)
        {}
      };

      template < size_t NB_STATES >
      class XmlParser {

        using U_StateArray = std::array<XmlState, NB_STATES>;
        U_StateArray  m_states;

        public:
          XmlParser
            (std::initializer_list<typename U_StateArray::value_type> states)
            : m_states{states}
          {}

      };

      XmlParser<1>  test {
      {
        {
            XmlState::U_StateFunc(), XmlState::U_StateFunc(),
            {
              { "Tag1", []() {} },
              { "Tag2", []() {} },
              { "Tag3", []() {} }
            }
        }
      }};

int main() {}

Wandbox

I'm wondering why I struggle so much to use this. {} this is a std::initializer_list empty, and {{}} this is one with one element right? But you need to put them inside the constructor like Foo({{}}) ? Or using another list Foo{{{}}}. I mean, this looks simple, but I just can't make it happen.

Btw I'd like to know if it's better to use initializer_list or template parameter pack? Both with move semantic, because there is no temporary object with parameter pack after all?

2
  • std::array can use aggregate initialization but it does not have a constructor that can deal with std::initializer_list. Commented Feb 25, 2018 at 13:06
  • @super I tried with parameter pack without success too. Do you have any clues? Commented Feb 25, 2018 at 15:24

1 Answer 1

1

Not sure if this is what you are looking for, but if you change XmlParser to take a U_StateArray in the constructor, you can make the syntax close to your original.

//Changed constructor in XmlParser
XmlParser (U_StateArray states) : m_states{states} {}

//Used like this
XmlParser<2>  test {{

        XmlState(XmlState::U_StateFunc(), XmlState::U_StateFunc(),
        {
          { "Tag1", []() {} },
          { "Tag2", []() {} },
          { "Tag3", []() {} }
        }),

        XmlState(XmlState::U_StateFunc(), XmlState::U_StateFunc(),
        {
          { "Tag4", []() {} },
          { "Tag5", []() {} }
        })

}};

Another option is to change the std::array to a std::vector. Then your code works since std::vector has a constructor for std::initializer_list.

A third option is to make a helper, that takes an std::initializer_list and returns an appropriate std::array. Like suggested here.

Sign up to request clarification or add additional context in comments.

1 Comment

Just moving a array, simple and efficient. I was too focus on how to foward the arguments ^^" Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.