Background:
I'm trying to port a library to compile on MSVC.
That library stores data in a tuple of vectors (std::tuple<std::vector<Ts>...>
), and uses a custom iterator to iterate over all vectors simultaneously (similar to what a zip_iterator does).
The iterator defines types that look like this (assuming Ts...
-> <int, int>
) :
`value_type` is `std::tuple<int, int>`
`reference` is `std::tuple<int&, int&>`
The problem is that on latest MSVC (v. 19.35), this iterator does not satisfy the concept of std::input_iterator
, while it does satisfy it on gcc/clang.
On further investigation, i found the failure to be due to inconsistent behaviour of the std::common_reference
concept on tuples.
Issue:
The following static_assert
fails on MSVC, while it doesn't fail on 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");
Here it is on Godbolt (with an iterator example as well)
Question:
Is a type like std::tuple<int, int>&
supposed to have a "common_reference_with
" std::tuple<int&, int&>
? MSVC says no, gcc says yes.
Which of the two behaviours should be expected according to the standard in C++20 and forward?
Is there any easy way to make this iterator succeed the iterator concept checks on MSVC (ie, force the two types to have a common reference)?
I also found some great answers by Eric Niebler, on std::common_reference (SO) and on proxy iterators (on his blog).
However, it's not clear to me what is supposed to happen in C++20 and later.