Почему тип boost :: hana :: tuple_c определяется реализацией?

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 обертка лишняя?

2

Решение

Фраза «определенная реализация» не описывает реализацию. В нем прямо говорится, что выбор реализации оставлен недокументированным специально по той или иной причине. Конечно это реализовано как-то. Пользователи не должны полагаться на какую-либо конкретную реализацию, а использовать только документированные API.

Оставить выбор реализации недокументированным — разумное значение по умолчанию, если только нет особой причины его документировать. Это верно, даже если есть только один очевидный выбор сегодня, потому что завтра все может измениться.

3

Другие решения

Собственно, документация это покрыто в FAQ:

Зачем оставлять представление некоторого контейнера определенным реализацией?

Во-первых, это дает гораздо больше возможностей для реализации
выполнять оптимизацию во время компиляции и во время выполнения с использованием умного
представления для конкретных контейнеров. Например, кортеж
содержащие однородные объекты типа T могут быть реализованы как
вместо этого массив типа T, который более эффективен во время компиляции.
Во-вторых, и самое главное, получается, что зная тип
гетерогенный контейнер не так полезен, как вы думаете. В самом деле,
в контексте гетерогенного программирования, тип объекта
возвращаемое вычислением обычно тоже является частью вычисления. В
Другими словами, нет способа узнать тип возвращаемого объекта.
по алгоритму без фактического выполнения алгоритма.

2

Не говорю с властью, но я бы сказал, что упаковка tuple_c с to_tuple на самом деле лишнее. В документации говорится, что результат функционально эквивалентный в make_tuple за исключением того, что тип не гарантируется быть тем же самым.

Одна возможная оптимизация будет возвращать что-то вроде этого:

template <auto ...i>
struct tuple_c_t { };

Чтобы быть уверенным, я сделал запрос на выборку, чтобы посмотреть, сможем ли мы удалить лишнее преобразование из примера.

https://github.com/boostorg/hana/pull/394

ОБНОВИТЬ: Автор Boost.Hana подтвердил, что преобразование не нужно, и пример был обновлен, чтобы отразить это.

2
По вопросам рекламы [email protected]