c++ 如何将boost::hana::Sequence的元素都满足一个概念表述为一个概念?

b1payxdu  于 2023-03-05  发布在  其他
关注(0)|答案(1)|浏览(101)

假设我有以下概念:

#include <boost/hana.hpp>
#include <iostream>
namespace hana = boost::hana;
   
// this is only for consistency
template <typename S> concept hana_sequence = hana::Sequence<S>::value;

template <typename T> concept callable_with_int = requires(T&& t, int i) { t(i); };

我想定义在hana_sequence上工作的函数,其元素都满足这个概念,例如:

void applyCallable(const sequence_of_callables auto& ha, int i)
{
  hana::for_each(ha, [&] (auto e) {std::cerr<<"inside apply – "; e(i);});
}

int main()
{
  applyCallable(hana::make_tuple(
    [] (int i) {std::cerr<<"inside lambda0 "<<2*i<<"!\n";},
    [] (int i) {std::cerr<<"inside lambda1 "<<i<<"!\n";}/*,
    [] () {std::cerr<<"inside lambda2!\n";}*/ // this would spoil compilation, as expected
  ),4);
}

我的问题是如何将sequence_of_callables定义为一个C++20概念。经过一些磨难,我想出了下面的解决方案:

// spurious helper needed?
template <typename T> constexpr bool sequenceOfCallablesHelper = false;

template <typename... T> constexpr bool sequenceOfCallablesHelper<hana::tuple<T...>>
  = hana::fold(hana::tuple_t<T...>, true, [] (bool s, auto element) {
    return s && callable_with_int<typename decltype(element)::type>;});

template <typename S>
concept sequence_of_callables = ( hana_sequence<S> && sequenceOfCallablesHelper<S> );

这和预期的一样,但是对helper及其专门化的需求有点难看。
是否可以更直接地做到这一点?

0g0grzrc

0g0grzrc1#

您可以先使用hana::transformShana::tuple<T...>转换为hana::tuple<hana::type<T>...>,然后使用hana::all_of检查每个类型是否满足callable_with_int概念:

#include <boost/hana.hpp>

namespace hana = boost::hana;

// this is only for consistency
template <typename S> 
concept hana_sequence = hana::Sequence<S>::value;

template <typename T> 
concept callable_with_int = requires(T&& t, int i) { t(i); };

template <typename S>
concept sequence_of_callables = hana_sequence<S> && 
  !!hana::all_of(
    decltype(hana::transform(std::declval<S>(), hana::typeid_)){},
    []<class T>(T) { return callable_with_int<typename T::type>; });

demo

相关问题