Fundo:
Estou tentando portar uma biblioteca para compilar no MSVC. Essa biblioteca armazena dados em uma tupla de vetores ( std::tuple<std::vector<Ts>...>
) e usa um iterador personalizado para iterar todos os vetores simultaneamente (semelhante ao que faz um zip_iterator).
O iterador define tipos que se parecem com isso (assumindo Ts...
-> <int, int>
):
`value_type` is `std::tuple<int, int>`
`reference` is `std::tuple<int&, int&>`
O problema é que no MSVC mais recente (v. 19.35), esse iterador não satisfaz o conceito de std::input_iterator
, embora o satisfaça no gcc/clang.
Em uma investigação mais aprofundada, descobri que a falha se deve ao comportamento inconsistente do std::common_reference
conceito em tuplas.
Emitir:
O seguinte static_assert
falha no MSVC, enquanto não falha no 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");
Aqui está em Godbolt (com um exemplo de iterador também)
Pergunta:
Um tipo como std::tuple<int, int>&
deveria ter um " common_reference_with
" std::tuple<int&, int&>
? MSVC diz que não, gcc diz que sim.
Qual dos dois comportamentos deve ser esperado de acordo com o padrão em C++20 e posteriores?
Existe alguma maneira fácil de fazer com que esse iterador seja bem-sucedido nas verificações de conceito do iterador no MSVC (ou seja, forçar os dois tipos a terem uma referência comum)?
Também encontrei ótimas respostas de Eric Niebler, em std::common_reference (SO) e em proxy iterators (em seu blog) .
No entanto, não está claro para mim o que deve acontecer no C++ 20 e posterior.
Sim, o P2321 garante que eles tenham tipo
tuple<int&, int&>
e modelo de referência comunscommon_reference_with
.Como esse aprimoramento do
common_reference
fortuple
é um recurso do C++23, você precisa alterar a opção do compilador MSVC para/std:c++latest
fazê -lo funcionar .Vale a pena notar que o P2165 é
tuple
compatível com outrostuple
objetos semelhantes a - comoarray
,pair
eranges::subrange
, portanto também possui umcommon_reference
tipo válido com os outros três.