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

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


11

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.

Share
Improve this question

New contributor

Panagiotis Syskakis is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

1 Answer
1

Reset to default


10

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.

Share
Improve this answer



Not the answer you're looking for? Browse other questions tagged

or ask your own question.

Leave a Reply

Your email address will not be published. Required fields are marked *