I want the following code to compile and work:
#include <boost/hana/group.hpp>
#include <functional>
#include <vector>
int main() {
std::vector<int> x = {1,1,3,4};
auto groups = boost::hana::group(x, std::equal_to<>{});
}
An attempt to compile errors like this:
$ g++ -std=c++2a deleteme.cpp && ./a.out
In file included from deleteme.cpp:1:
/usr/include/boost/hana/group.hpp: In instantiation of ‘constexpr auto boost::hana::group_t::operator()(Xs&&, Predicate&&) const [with Xs = std::vector<int>&; Predicate = std::equal_to<void>]’:
deleteme.cpp:6:44: required from here
/usr/include/boost/hana/group.hpp:55:42: error: static assertion failed: hana::group(xs, predicate) requires 'xs' to be a Sequence
55 | static_assert(hana::Sequence<S>::value,
| ^~~~~
/usr/include/boost/hana/group.hpp:59:28: error: use of deleted function ‘static constexpr auto boost::hana::deleted_implementation::apply(T&& ...) [with T = {std::vector<int, std::allocator<int> >&, std::equal_to<void>}]’
59 | return Group::apply(static_cast<Xs&&>(xs),
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
60 | static_cast<Predicate&&>(pred));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/hana/core/dispatch.hpp:14,
from /usr/include/boost/hana/drop_front.hpp:18,
from /usr/include/boost/hana/concept/iterable.hpp:20,
from /usr/include/boost/hana/at.hpp:16,
from /usr/include/boost/hana/group.hpp:15,
from deleteme.cpp:1:
/usr/include/boost/hana/detail/dispatch_if.hpp:21:31: note: declared here
21 | static constexpr auto apply(T&& ...) = delete;
| ^~~~~
Therefore I understand that the reason is that std::vector
does not satisfy the concept of Sequence
, but how do I enforce that it does?
I've been giving a look at /usr/include/boost/hana/fwd/concept/sequence.hpp
and /usr/include/boost/hana/concept/sequence.hpp
, but for now the template meta-metaprogramming in those files is still a bit to heavy for me to understand it without any help.
This is an excerpt from Hana's documentation, which I think addresses the question. The point is that I don't how I can translate that prescriptions to code:
For this reason, it is necessary to specialize the Sequence metafunction in Hana's namespace to tell Hana that a type is indeed a Sequence. Explicitly specializing the Sequence metafunction can be seen like a seal saying "this data type satisfies the additional laws of a
Sequence
", since those can't be checked by Hana automatically.
While it is possible to implement some of the concepts in Boost.Hana with types that involve different dimensions known only at run-time, Boost.Hana.Sequence and some of the concepts that are a part of its "Minimal Complete Definition" require length and elements to be known at compile-time.
Foldable
requires that the length be known at compile-time.Iterable
requires that each element be accessible at compile-time.Sequence
requires Foldable
and Iterable
.The group
function requiring a Sequence
and the run-time length of std::vector
make this impossible.
The section Computational Quadrants in the Boost.Hana manual elaborates on algorithms requiring compile-time vs run-time information.
(The Group
concept is likely doable, but I don't think that is part of the question.)
Regarding the comments about specializing third party templates for standard types, it is possible but considered bad form. The solution is to make a wrapper type of some kind or provide your own concepts.
Edit:
A comment suggested an example of implementing std::array
as a Sequence
since its length is known at compile-time. While I can't find a silver bullet in the "Laws" of Sequence
that forbid homogeneously typed lists, I can say that the premise of Sequence
is working with heterogeneously typed data structures. Elements may contain run-time data, but all of the predicates in the algorithms rely exclusively on "compile-time" information so functions like group
would be completely useless for std::array
. (This is explained in the aforementioned link)