Why is the type of boost::hana::tuple_c implementation-defined?

204 Views Asked by At

The Boost.Hana documentation for tuple_c states:

Also note that the type of the objects returned by tuple_c and an equivalent call to make<tuple_tag> may differ.

followed by the following snippet:

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>)
);

However, the actual implementation for tuple_c simply has:

#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

and, indeed, the code snippet works just fine without the to_tuple wrapper:

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>)
);

Question: why is the actual type of tuple_c implementation defined? Isn't the to_tuple wrapper superfluous?

3

There are 3 best solutions below

1
On BEST ANSWER

Actually, the documentation has this covered in a FAQ:

Why leave some container's representation implementation-defined?

First, it gives much more wiggle room for the implementation to perform compile-time and runtime optimizations by using clever representations for specific containers. For example, a tuple containing homogeneous objects of type T could be implemented as an array of type T instead, which is more efficient at compile-time. Secondly, and most importantly, it turns out that knowing the type of a heterogeneous container is not as useful as you would think. Indeed, in the context of heterogeneous programming, the type of the object returned by a computation is usually part of the computation too. In other words, there is no way to know the type of the object returned by an algorithm without actually performing the algorithm.

0
On

Not speaking with authority, but I would say that wrapping the tuple_c with to_tuple is in fact superfluous. The documentation states that the result is functionally equivalent to make_tuple except that the type is not guaranteed to be the same.

One possible optimization would be returning something like this:

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

To be sure I made a pull request to see if we can get the superfluous conversion removed from the example.

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

UPDATE: It was confirmed by the author of Boost.Hana that the conversion is unnecessary and the example was updated to reflect that.

3
On

The phrase "implementation defined" does not describe an implementation. It explicitly states that an implementation choice is left undocumented on purpose, for one reason or another. Of course it is implemented somehow. The users should not rely on any particular implementation but use only documented APIs.

Leaving an implementation choice undocumented is a sensible default unless there's a specific reason to document it. This is true even if there's only one obvious choice today, because tomorrow things may change.