我正在写一个zip_iterator
(为了好玩/学术/“哦,没有提升是邪恶的,我们不想要它”的原因)我设想的一个用例是压缩两个vector
s一起进入另一个容器,例如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 here的工作演示,GCC here和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对元素,一个应该可以从另一个构造。如果我试图找到一个泛型对(元组)构造函数,或者一个元组来配对隐式转换,我似乎找不到一个。那么问题就变成了:为什么它对Clang / libc ++起作用呢?
注意:我不能只在那里推std::make_pair
,因为它是通用代码。
一种可能的解决方法是特殊情况下使用双迭代器案例来生成pair
而不是tuple
。看起来很难看,但可行。如果可能的话,我宁愿避免这样做。
答案 0 :(得分: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中,您可以使用专精/ if constexpr
或static_if
替换enable_if
。