c++c++11

Complex constructor initialization for static const container


In my header file, within a class body, I declare a vector of tuples where everything is constant. This is just data that I'm going to walk through as I do a task...

class Foo {
 public:
  ...
  static const std::vector<std::tuple<const char*, int>> _data;

In the corresponding source file, I populate the data...

const std::vector<std::tuple<const char*, int>>
Foo::_data
{
  std::make_tuple("One",    1),
  std::make_tuple("Two",    2),
  ...
  std::make_tuple("Many",  10)
};

This throws a clang-tidy error cert-err58-cpp...

/path/to/src/Foo.cpp:783:14: warning: initialization of '_data' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
Foo::_data
     ^
/path/to/gcc-9.2.0/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../include/c++/9.2.0/bits/stl_vector.h:622:7: note: possibly throwing constructor declared here
      vector(initializer_list<value_type> __l,
      ^

I get that there are cases that a vector might not find space to store the data, so would throw an exception. Here, there is no way for me to try/catch it though. That feels overkill for this anyway. What is the best solution here...?

Using std::array instead of std::vector just pushes the problem down to make_tuple...

EDIT: Here is the code that I settled on. No source file additions. This is the header file...

static constexpr std::array<std::pair<const char*, int>, 10> _data {
{
  {{"One",  1},
   {"Two",  2},
   ...
   {"Ten", 10}}
};

Solution

  • a vector of tuples where everything is constant

    Why not an array of tuples where everything is constant?

    class Foo {
     public:
      static const std::array<std::tuple<const char*, int>, 10> _data;
    };
    
    const std::array<std::tuple<const char*, int>, 10>
    Foo::_data
    {{
      {"One",  1},
      {"Two",  2},
      ...
      {"Ten", 10},
    }};
    

    With constexpr

    class Foo {
     public:
      static constexpr std::array<std::tuple<const char*, int>, 10> _data = {{
        {"One", 1},
        {"Two", 2}
      }};
    };