std :: range :: elements_view для пользовательских данных, подобных кортежу - PullRequest
3 голосов
/ 09 июля 2020

У меня есть вариант использования, который можно сократить до:

#include <vector>
#include <ranges>
#include <tuple>

struct TDat
{
  double x, y;

  template <std::size_t I>
  friend double &get(TDat &Dat)
    { if constexpr (I == 0) return Dat.x; else return Dat.y; }

  template <std::size_t I>
  friend double const &get(TDat const &Dat)
    { if constexpr (I == 0) return Dat.x; else return Dat.y; }
};

namespace std
{

template <>
struct tuple_size<TDat> : integral_constant<size_t, 2u> {};

template <size_t I>
struct tuple_element<I, TDat>
  { using type = double; };

} // std

class TTable
{
private:
  std::vector<TDat> DatVec;

public:  
  auto GetxVec()
    { return std::views::keys(DatVec); }
};

Этот фрагмент кода не компилируется с G ++ 10, потому что TDat не моделирует __has_tuple_element<std::ranges::range_value_t<_Vp>, _Nm>. Проблема, похоже, в том, что эта концепция определяется как (https://github.com/gcc-mirror/gcc/blob/fab263ab0fc10ea08409b80afa7e8569438b8d28/libstdc%2B%2B-v3/include/std/ranges#L3318):

  namespace __detail
  {
    template<typename _Tp, size_t _Nm>
    concept __has_tuple_element = requires(_Tp __t)
      {
    typename tuple_size<_Tp>::type;
    requires _Nm < tuple_size_v<_Tp>;
    typename tuple_element_t<_Nm, _Tp>;
    { std::get<_Nm>(__t) }
      -> convertible_to<const tuple_element_t<_Nm, _Tp>&>;
      };
  }

Я считаю, что, поскольку вызов get квалифицирован, компилятор не может найти мои get функции. Это правильный вывод? Если да, то это предполагаемое поведение? Определено ли поведение для определения моих функций get в пространстве имен std?

1 Ответ

2 голосов
/ 09 июля 2020

Я считаю, что, поскольку вызов get квалифицирован, компилятор не может найти мои get функции. Правильно ли этот вывод?

Да.

Если да, то это предполагаемое поведение?

Это указано поведение минимум. [range.elements.view] определяет понятие как:

  template<class T, size_t N>
  concept has-tuple-element =                   // exposition only
    requires(T t) {
      typename tuple_size<T>::type;
      requires N < tuple_size_v<T>;
      typename tuple_element_t<N, T>;
      { get<N>(t) } -> convertible_to<const tuple_element_t<N, T>&>;
    };

где все вызовы функций в стандартной библиотеке неявно полностью квалифицируются, если не указано иное [library.contents] / 3 :

Каждый раз, когда упоминается имя x, определенное в стандартной библиотеке, предполагается, что имя x полностью определено как ​::​std​::​x, если явно не указано иное.

Здесь нет другого описания.

Однако, предназначено это или нет - другой вопрос. И ответ тоже есть. Да, в Библиотеке нет концепции TupleLike. Да, структурированные привязки существуют, но формальной спецификации этого в Библиотеке пока нет - так что пока это не произойдет, все алгоритмы, подобные кортежу, работают только для вещей, подобных кортежу стандартной библиотеки (pair, array, tuple , et c.)

Определено ли поведение для определения моих функций get в пространстве имен std?

Нет, нельзя.

...