如何将元组插入地图?

How to insert a tuple into a map?

我正在写一个 zip_iterator(出于 fun/academic/"oh noes Boost is evil we don't want it" 原因),我设想的一个用例是将两个 vector 压缩到另一个容器中,例如 map。这适用于带有 libc++ 的 Clang,但在 MSVC2017 和 GCC 7.2 上意外失败。我将问题简化为这段代码:

#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.);
}

Clang here, broken demo's for GCC here and MSVC here 的工作演示。

这使得我的 zip_iterator 无法正常使用:

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

查看 zip_iterator 中的 here for the full code,因为我现在有它。

我希望它能工作,因为元组是一个 2 对元素,一个应该可以从另一个构造。如果我试图找到一个通用的 pair(tuple) 构造函数,或者一个元组来配对隐式转换,我似乎找不到。那么问题就变成了:为什么它完全适用于 Clang/libc++?

注意:我不能只在其中插入一个 std::make_pair,因为它是通用代码。

一种可能的解决方法是对双迭代器的情况进行特殊处理,以生成 pair 而不是 tuple。看起来很难看,但可行。如果可能的话,我宁愿避免这种情况。

and one should be constructible from the other

  • std::pair<T, U> 没有定义来自 std::tuple<T, U> 的任何隐式构造函数。

  • 同理,std::tuple<T, U>不 将任何隐式转换运算符定义为 std::pair<T, U>.

我认为Clang (libc++)在这里是不正确的,GCC和MSVC是正确的。


Seems ugly, but doable

还不错:

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)...);
    } 
}

在 C++14 中,您可以将 if constexpr 替换为 specialization/enable_ifstatic_if.