#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
в качестве точек настройки. Основное правило, грубо говоря,
- сначала обрабатываются встроенные массивы;
- затем проверьте
tuple_size<T>::value
; - если это не удается, проверьте, есть ли в классе все общедоступные элементы данных.
Для надежной работы шага # 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
вообще не должны иметь.