1

Below is code that adds elements to a vector containing a std::pair

std::vector<std::pair<std::string, std::type_index>> args_;

template <class T>
            inline OperationEntry& setArg(const std::string& name)
            {
                args_.push_back({name, typeid(T)});
                return *this;

            }

How do I add elements to a vector containing a std::tuple?

std::vector<std::tuple<std::string, std::type_index, Attribute>> args_;

template <class T>
            inline OperationEntry& setArg(const std::string& name, Attribute value = Attribute())
            {
                args_.push_back({name, typeid(T), value});
                return *this;

            }

I tried args_.push_back(std::make_tuple(name, typeid(T), value));

I am getting this error:

[GCC] converting to
‘std::vector<std::tuple<std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::type_index,
mv::Attribute> >::value_type {aka
std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >, std::type_index, mv::Attribute>}’ from
initializer list would use explicit constructor ‘constexpr std::tuple<
<template-parameter-1-1> >::tuple(_UElements&& ...) [with _UElements =
{const std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >&, const std::type_info&, mv::Attribute&};
<template-parameter-2-2> = void; _Elements =
{std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >, std::type_index, mv::Attribute}]’
Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
cherry aldi
  • 327
  • 1
  • 10
  • That is not the full error message. – LogicStuff Nov 28 '18 at 18:21
  • 1
    [WFM](http://coliru.stacked-crooked.com/a/b443d5e5ee2f7889) though I did have to remove `Attribute` (because I have no idea what it is) so maybe that's why. As ever, please present your [MCVE]. This is not optional. – Lightness Races in Orbit Nov 28 '18 at 18:32
  • See also [Why ={} initialization doesn't work for tuple?](https://stackoverflow.com/questions/32084706/why-initialization-doesnt-work-for-tuple) – Vadzim Feb 08 '19 at 16:51

1 Answers1

4
args_.push_back({name, typeid(T), value});

Before N4387, std::tuple's constructor used for the above initialization was unconditionally explicit, and if selected by overload resolution in a copy-list-initialization, the compiler was allowed to raise an error.


args_.push_back(std::make_tuple(name, typeid(T), value));

The above call will try to use a copy-constructor for an std::type_info instance which is non-copyable.


In order to construct a tuple in a pre-N4387 implementation, use emplace_back:

args_.emplace_back(name, typeid(T), value);

or push back a tuple of copy-constructible types:

args_.push_back(std::make_tuple(name, std::type_index{typeid(T)}, value));
//                                         ~~~~~~~~~^
Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
  • N4387 is implemented in GCC 6.1: https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html – Vadzim Feb 08 '19 at 16:54