简体   繁体   中英

How to insert a tuple into a map?

I was writing a zip_iterator (for fun/academic/"oh noes Boost is evil we don't want it" reasons) and one of the use cases I envisioned is zipping two vector s together into another container, such as a map . This worked on Clang with libc++, but failed unexpectedly on MSVC2017 and GCC 7.2. I reduced the problem to this code:

#include <iterator>
#include <map>
#include <tuple>

int main()
{
    std::map<int, double> map;

    auto it = std::inserter(map, map.begin());

    it = std::make_tuple(1, 1.);
}

Working demo for Clang here , broken demo's for GCC here and MSVC here .

This makes elegant use of my zip_iterator not work:

std::copy(zip_begin(ints, doubles), zip_end(ints, doubles), std::inserter(int_double_map, int_double_map.begin()));

See here for the full code of that zip_iterator as I have it now.

I expect this to work because a tuple is a 2-pair element and one should be constructible from the other. If I try to find a generic pair(tuple) constructor, or a tuple to pair implicit conversion, I can't seem to find one. So then the question becomes: why does it work on Clang/libc++ at all?

Note: I can't just shove an std::make_pair in there, because, well, it's generic code.

A possible workaround would be to special-case the two-iterator case to produce a pair instead of a tuple . Seems ugly, but doable. I'd rather avoid that if at all possible.

and one should be constructible from the other

  • std::pair<T, U> does not define any implicit constructor from std::tuple<T, U> .

  • Similarly, std::tuple<T, U> does not define any implicit conversion operator to std::pair<T, U> .

I think Clang (libc++) is incorrect here, and that GCC and MSVC are correct.


Seems ugly, but doable

It's not too bad:

template <typename... Ts> 
auto make_thing(Ts&&... xs)
{
    if constexpr(sizeof...(xs) == 2)) 
    { 
        return std::make_pair(std::forward<Ts>(xs)...);
    }
    else
    {
        return std::make_tuple(std::forward<Ts>(xs)...);
    } 
}

In C++14, you can replace if constexpr with specialization/ enable_if or static_if .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM