3

Consider this code:

  std::vector<
          std::tuple<std::vector<std::size_t>,
                     std::vector<std::size_t>,
                     std::vector<std::size_t>>
        > foo = {
        {{2, 1, 2, 3},   {1, 2},  {2, 3}},
        {{2, 3, 4, 0},   {3},     {2, 3, 4}},
        {{2, 3, 4, 0},   {0},     {3, 4, 0}},
      };

In Clang, and GCC 6 or later it compiles fine. In GCC 5.5 it gives this error:

 In function 'int main()':

:16:4: error: converting to
          'std::tuple<std::vector<long unsigned int, std::allocator<long unsigned int> >,
                      std::vector<long unsigned int, std::allocator<long unsigned int> >,
                      std::vector<long unsigned int, std::allocator<long unsigned int> > >'
      from initializer list would use explicit constructor
          'constexpr std::tuple< <template-parameter-1-1> >::tuple(const _Elements& ...)
     [with _Elements = {
           std::vector<long unsigned int, std::allocator<long unsigned int> >, std::vector<long unsigned int, std::allocator<long unsigned int> >, std::vector<long unsigned int, std::allocator<long unsigned int> >}]'

    };

    ^

Why is this and how can I work around it?

Timmmm
  • 88,195
  • 71
  • 364
  • 509
  • 1
    IIRC The GCC 5 series uses C++11 as default, while GCC 6 and 7 series uses C++14 as default. And there are some changes between the standards for [the `std::tuple` constructor](http://en.cppreference.com/w/cpp/utility/tuple/tuple). Those changes might have something to do with your problem. – Some programmer dude May 18 '18 at 13:57
  • @Someprogrammerdude Apparently [that's not it](https://godbolt.org/g/Qyxuzg). – HolyBlackCat May 18 '18 at 13:59
  • 1
    [See notes paragraph](http://en.cppreference.com/w/cpp/utility/tuple/tuple). This is a feature of C++17. I guess support for it was added in GCC 6. – Yksisarvinen May 18 '18 at 13:59
  • Looks like this might work for you: https://stackoverflow.com/questions/12436586/tuple-vector-and-initializer-list – NathanOliver May 18 '18 at 14:00
  • You can work around by calling all the constructors explicitly. – OutOfBound May 18 '18 at 14:00

1 Answers1

3

One possible workaround is to call tuple constructor explicitly:

using bar = std::tuple<std::vector<std::size_t>,
                       std::vector<std::size_t>,
                       std::vector<std::size_t>>;
std::vector<bar> foo = {
    bar{{2, 1, 2, 3},   {1, 2},  {2, 3}},
    bar{{2, 3, 4, 0},   {3},     {2, 3, 4}},
    bar{{2, 3, 4, 0},   {0},     {3, 4, 0}},
};

(Live demo)

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207