Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Inconsistent behavior of std::common_reference_with on tuples. Which is correct?

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

>Solution :

Is a type like std::tuple<int, int>& supposed to have a
"common_reference_with" std::tuple<int&, int&> ?

Yes, P2321 guarantees that they have common reference type tuple<int&, int&> and model common_reference_with.

Since such enhancement of common_reference for tuple is a C++23 feature, you need to change the MSVC compiler option to /std:c++latest to make it work.

It is worth noting that P2165 makes tuple compatible with other tuple-like objects such as array, pair and ranges::subrange, so it also has a valid common_reference type with the other three.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading