Search code examples
c++boostc++14template-meta-programmingboost-hana

Why is boost::hana's set not default constructable?


today I found that boost::hana's map and set aren't default constructable, while the tuple is. Is there any particular reason for this because it is quite annoying.

This

#include <boost/hana/set.hpp> 
//                   ^^^ or map

constexpr boost::hana::set<> a{};
//                     ^^^ or map

int main(){}

fails with the following error:

main.cpp:3:30: error: no matching constructor for initialization of 'const boost::hana::set<>'
constexpr boost::hana::set<> a{};
                             ^~~
/home/russellg/Documents/boost/hana-0.6.0/include/boost/hana/set.hpp:65:28: note: candidate constructor not viable: requires single argument 'xs', but no arguments were provided
        explicit constexpr set(tuple<Xs...> const& xs)
                           ^
/home/russellg/Documents/boost/hana-0.6.0/include/boost/hana/set.hpp:69:28: note: candidate constructor not viable: requires single argument 'xs', but no arguments were provided
        explicit constexpr set(tuple<Xs...>&& xs)
                           ^
/home/russellg/Documents/boost/hana-0.6.0/include/boost/hana/set.hpp:57:12: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were
      provided
    struct set
           ^
/home/russellg/Documents/boost/hana-0.6.0/include/boost/hana/set.hpp:57:12: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were
      provided
1 error generated.

even though it is perfectly valid to have an empty map or set:

#include <boost/hana/set.hpp>
//                   ^^^ or map

constexpr auto a = boost::hana::make_set();
//                                   ^^^ or map

int main(){}

Which compiles flawlessly.

Any help is appreciated.

EDIT:

It doesn't actually matter if it is empty, it is always illegal to default construct maps and sets.


Solution

  • The hana::set and hana::map representations are implementation-defined. The documentation warns against their direct usage and mentions that the canonical way to create these is via hana::make_set and hana::make_map respectively. The documentation states:

    The actual representation of a hana::set is implementation-defined. In particular, one should not take for granted the order of the template parameters and the presence of any constructor or assignment operator. The canonical way of creating a hana::set is through hana::make_set.

    hana::tuple is a simpler container, documents its representation, and strives to maintain some parity with std::tuple. The hana::basic_tuple documentation notes:

    [...] hana::tuple aims to provide an interface somewhat close to a std::tuple [...]


    As to why hana::set and hana::map's representations are implementation-defined, consider reading the FAQ, but in short:

    • allows more flexibility to implement compile-time and runtime optimizations
    • knowing the type is usually not very useful

    There is a github issue to consider adding a default-constructor for hana::map.