Boost.Hana документация за tuple_c
состояния:
Также обратите внимание, что тип объектов, возвращаемых
tuple_c
и
эквивалентный вызовmake<tuple_tag>
может отличаться
сопровождается следующим фрагментом:
BOOST_HANA_CONSTANT_CHECK(
hana::to_tuple(hana::tuple_c<int, 0, 1, 2>)
==
hana::make_tuple(hana::int_c<0>, hana::int_c<1>, hana::int_c<2>)
);
Тем не менее фактическая реализация за tuple_c
просто имеет:
#ifdef BOOST_HANA_DOXYGEN_INVOKED
template <typename T, T ...v>
constexpr implementation_defined tuple_c{};
#else
template <typename T, T ...v>
constexpr hana::tuple<hana::integral_constant<T, v>...> tuple_c{};
#endif
и действительно, фрагмент кода работает просто отлично без to_tuple
обертка:
BOOST_HANA_CONSTANT_CHECK(
hana::tuple_c<int, 0, 1, 2>
==
hana::make_tuple(hana::int_c<0>, hana::int_c<1>, hana::int_c<2>)
);
Вопрос: почему фактический тип tuple_c
реализация определена? Разве не to_tuple
обертка лишняя?
Фраза «определенная реализация» не описывает реализацию. В нем прямо говорится, что выбор реализации оставлен недокументированным специально по той или иной причине. Конечно это реализовано как-то. Пользователи не должны полагаться на какую-либо конкретную реализацию, а использовать только документированные API.
Оставить выбор реализации недокументированным — разумное значение по умолчанию, если только нет особой причины его документировать. Это верно, даже если есть только один очевидный выбор сегодня, потому что завтра все может измениться.
Собственно, документация это покрыто в FAQ:
Зачем оставлять представление некоторого контейнера определенным реализацией?
Во-первых, это дает гораздо больше возможностей для реализации
выполнять оптимизацию во время компиляции и во время выполнения с использованием умного
представления для конкретных контейнеров. Например, кортеж
содержащие однородные объекты типа T могут быть реализованы как
вместо этого массив типа T, который более эффективен во время компиляции.
Во-вторых, и самое главное, получается, что зная тип
гетерогенный контейнер не так полезен, как вы думаете. В самом деле,
в контексте гетерогенного программирования, тип объекта
возвращаемое вычислением обычно тоже является частью вычисления. В
Другими словами, нет способа узнать тип возвращаемого объекта.
по алгоритму без фактического выполнения алгоритма.
Не говорю с властью, но я бы сказал, что упаковка tuple_c
с to_tuple
на самом деле лишнее. В документации говорится, что результат функционально эквивалентный в make_tuple
за исключением того, что тип не гарантируется быть тем же самым.
Одна возможная оптимизация будет возвращать что-то вроде этого:
template <auto ...i>
struct tuple_c_t { };
Чтобы быть уверенным, я сделал запрос на выборку, чтобы посмотреть, сможем ли мы удалить лишнее преобразование из примера.
https://github.com/boostorg/hana/pull/394
ОБНОВИТЬ: Автор Boost.Hana подтвердил, что преобразование не нужно, и пример был обновлен, чтобы отразить это.