Реализация структурированных привязок под землей и std:: tuple

#c #clang #c 17 #stdtuple #structured-bindings

#c #лязг #c 17 #stdtuple #структурированные привязки

Вопрос:

Правда ли, что структурированные привязки в clang (я использую недавно clang version 4.0.0 (trunk 282683) созданные) реализованы с использованием некоторых элементов <tuple> , например, фигурные скобки -списки инициализации могут использовать элементы из <initializer_list> ?

Я написал простой код, просто чтобы поиграть с некоторыми из последних реализованных функций:

 struct S { int a; char b; double c; };
auto [a, b, c] = S{1, '2', 3.0};
using A = decltype(a);
using A = int;
using B = decltype(b);
using B = char;
using C = decltype(c);
using C = double;
  

Пока все хорошо, но когда я добавляю const квалификатор перед auto :

 struct S { int a; char b; double c; };
const auto [a, b, c] = S{1, '2', 3.0};
using A = decltype(a);
using A = int const;
using B = decltype(b);
using B = char const;
using C = decltype(c);
using C = double const;
  

Я получаю странное описание ошибки:

 In file included from /home/user/test/main.cpp:1:
In file included from /home/user/test/./test.hpp:4:
In file included from /usr/local/bin/../include/c  /v1/utility:193:
/usr/local/bin/../include/c  /v1/__tuple:29:14: fatal error: implicit instantiation of undefined template 'std::__1::tuple_size<S>'
    : public tuple_size<_Tp> {};
             ^
/home/user/test/main.cpp:110:16: note: in instantiation of template class 'std::__1::tuple_size<const S>' requested here
    const auto [a, b, c] = S{1, '2', 3.0};
               ^
/usr/local/bin/../include/c  /v1/__tuple:25:50: note: template is declared here
template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size;
                                                 ^
  

Т.е. происходит взаимодействие со случайно включенным <tuple> .

Я знаю, что структурированные привязки частично реализованы clang , но в любом случае интересно, как <tuple> это может быть связано с ними?

Должен ли я включать <tuple> использование структурированных привязок?

Дополнительные:

auto auto amp; и auto amp;amp; работает, но auto const и auto const amp; нет.

Комментарии:

1. Использование std::tie реализации было бы для меня естественным…

2. @W.F. Другой способ — сделать функцию встроенной.

3. Я имею в виду базовую реализацию 🙂 но я знаю, что это не отвечает на ваш вопрос…

4. См. LWG 2770 . Вы можете ожидать, что это будет исправлено до отправки C 17.

5. @WF tie было бы для меня совершенно неестественно, но неважно.

Ответ №1:

Да, структурированная привязка использует tuple_size и tuple_element в качестве точек настройки. Основное правило, грубо говоря,

  1. сначала обрабатываются встроенные массивы;
  2. затем проверьте tuple_size<T>::value ;
  3. если это не удается, проверьте, есть ли в классе все общедоступные элементы данных.

Для надежной работы шага # 2 tuple_size необходимо, чтобы он был дружественным к SFINAE, но tuple_size<cv T> в настоящее время не требуется, чтобы он был дружественным к SFINAE. Отсюда и ошибка.

Комментарии:

1. Интересно, как выглядит эквивалентный (псевдо) код (например, существующий для ranged for -loop) такого алгоритма на основе SFINAE. Почему, если <tuple> не включено, здесь нет серьезной ошибки? Это странно. Потому что, если нет символа std::tuple_size , то здесь определенно должна быть серьезная ошибка, но это не так. В то время как нарушение SFINAE-дружественности tuple_size<cv T> приводит к серьезной ошибке.

2. @Orient Это специальная конструкция основного языка; он не должен подчиняться (обычным) правилам SFINAE. И, возможно, не вызывать серьезную ошибку при отсутствии tuple_size имеет смысл, потому что автономные реализации tuple_size вообще не должны иметь.