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 vectors 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With