背景:
我正在尝试移植一个库以在 MSVC 上进行编译。该库将数据存储在向量元组 ( std::tuple<std::vector<Ts>...>
) 中,并使用自定义迭代器同时迭代所有向量(类似于 zip_iterator 的作用)。
迭代器定义的类型如下所示(假设Ts...
-> <int, int>
):
`value_type` is `std::tuple<int, int>`
`reference` is `std::tuple<int&, int&>`
问题是,在最新的 MSVC (v. 19.35) 上,这个迭代器不满足 的概念std::input_iterator
,而在 gcc/clang 上却满足它。
经过进一步调查,我发现失败是由于std::common_reference
元组上的概念行为不一致造成的。
问题:
以下static_assert
内容在 MSVC 上失败,而在 gcc/clang 上不会失败
using T = std::tuple<int, int>&;
using U = std::tuple<int&, int&>;
static_assert(std::common_reference_with<T, U>, "failed common_reference_with");
这是Godbolt上的(还有一个迭代器示例)
问题:
像这样的类型std::tuple<int, int>&
应该有一个“ common_reference_with
”std::tuple<int&, int&>
吗?MSVC 说不,gcc 说可以。
根据 C++20 及以后的标准,这两种行为中的哪一种是预期的?
是否有任何简单的方法可以使该迭代器成功通过 MSVC 上的迭代器概念检查(即强制这两种类型具有共同的引用)?
我还在 Eric Niebler 的std::common_reference (SO)和代理迭代器(在他的博客上)上找到了一些很好的答案。
但是,我不清楚 C++20 及更高版本中应该发生什么。
是的,P2321保证它们具有共同的参考类型
tuple<int&, int&>
和型号common_reference_with
。common_reference
由于for的此类增强tuple
是 C++23 功能,因此您需要将 MSVC 编译器选项更改为/std:c++latest
才能使其工作。值得注意的是,P2165
tuple
与其他tuple
类似对象(例如array
、pair
和 )兼容,因此它也与其他三个对象ranges::subrange
具有有效类型。common_reference