如何将元组插入到映射中?

3

我正在编写一个zip_iterator(出于兴趣、学术或者“哦不,Boost很邪恶,我们不想用它”的原因),其中我设想的一个使用场景是将两个vector压缩到一起放入另一个容器中,比如一个map。这在使用Clang和libc++时可以正常工作,但在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的工作演示,这里这里是GCC和MSVC的损坏演示。

这使得我的zip_iterator无法优雅地使用:

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

请参阅此处完整代码,我现在已经有了zip_iterator

我期望这能够工作,因为元组是一个2对元素,应该可以从另一个元组中构造出来。如果我尝试查找一个通用的对(元组)构造函数或从元组到对的隐式转换,看起来好像没有找到。那么问题就变成了:为什么它可以在Clang/libc++上工作呢?

注意:我不能只是把std::make_pair塞进去,因为这是通用代码。

一个可能的解决方法是将两个迭代器的情况特殊处理,以产生一个pair而不是tuple。看起来很丑陋,但是可行的。如果可能的话,我宁愿避免这种情况。


这是通用代码,一个 map 总是会使用 std::pair。那么通用部分在哪里呢? - user2672107
1个回答

4

并且一个应该能够从另一个构建

  • std::pair<T, U>不会隐式地从std::tuple<T, U>定义任何构造函数。

  • 同样,std::tuple<T, U>不会定义任何隐式的转换运算符到std::pair<T, U>

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


看起来很丑,但可行

它并不太糟:

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中,你可以使用特化/enable_ifstatic_if替换if constexpr

1
libc++只是提供了一个符合标准的扩展吗?还是真的不正确? - rubenvb
1
@rubenvb 如果在使用时它没有发出诊断消息(警告),那么该扩展就不符合规范。 - eerorika
你链接到了错误的页面,应该是 std::tuple :P - Rakete1111
@Vittoreo 是的,那基本上就是我所想的 :)。 - rubenvb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接