Я писал некоторые проекты, основанные на политике / особенностях, и натолкнулся на проблему с Boost :: mp11, которую я не понимаю. Я свел проблему к следующему примеру:
#include <iostream>
#include <variant>
#include <tuple>
#include <boost/hana/string.hpp>
#include <boost/mp11/algorithm.hpp>
using namespace boost::hana::literals;
struct stub_trait1
{
static constexpr auto name = "stub_trait1"_s;
};
struct stub_trait2
{
static constexpr auto name = "stub_trait2"_s;
};
struct test_card
{
using traits_type = std::tuple<stub_trait1, stub_trait2>;
explicit test_card() = default;
traits_type traits;
};
using cards_t = std::variant<test_card>;
template <typename TraitName>
struct trait_name_predicate
{
template <typename Trait>
struct result : std::is_same<decltype(Trait::name), TraitName> {};
};
template <typename TraitName, typename Callable>
void generic_trait_processor(const cards_t& card, const Callable& f)
{
std::visit([&](auto&& c) {
using traits_type = typename std::decay_t<decltype(c)>::traits_type;
using sr_idx = boost::mp11::mp_find_if<traits_type, trait_name_predicate<TraitName>::result>; // Fail!
if constexpr (sr_idx::value != std::tuple_size_v<traits_type>) {
auto& trait = std::get<sr_idx::value>(c.traits);
f(c, trait);
}
},
card);
}
int main()
{
auto c = cards_t{test_card{}};
generic_trait_processor<decltype("stub_trait1"_s)>(
c,
[](auto&& card, auto&& trait) {
std::cout << "Trait: " << trait.name << std::endl;
});
return EXIT_SUCCESS;
}
Вы можете (попытаться) запустить код Вот. Компилятор жалуется на boost::mp11::find_if
тип:
<source>: In lambda function:
<source>:42:100: error: type/value mismatch at argument 2 in template parameter list for 'template<class L, template<class ...> class P> using mp_find_if = typename boost::mp11::detail::mp_find_if_impl::type'
using sr_idx = boost::mp11::mp_find_if<traits_type, trait_name_predicate<TraitName>::result>;
^
<source>:42:100: note: expected a class template, got 'trait_name_predicate<TraitName>::result'
Ни одна из этих ошибок не имеет смысла, аргумент 2 является тип и trait_name_predicate<TraitName>::result
является шаблон класса!
Компилятор и я путаем друг друга — кто-нибудь может увидеть, что я делаю не так?
Мне нужно было сказать компилятору, что зависимое имя result
это шаблон:
using sr_idx = boost::mp11::mp_find_if<traits, trait_name_predicate<TraitName>::template result>;
^^^^
Других решений пока нет …