среда, 10 августа 2022 г.

[prog.c++.humour] Как можно сделать хуже в попытке сделать лучше

Выдалась возможность потратить некоторое время на очистку кода RESTinio от (полу)забытых FIXME. Один из них выглядит так:

templatetypename Extra_Data, typename Producer, typename Handler >
class actual_router_entry_t : public router_entry_t< Extra_Data >
{
   //FIXME: compatibility between Extra_Data and Handler should be
   //checked by static_assert. If it's possible.

Суть здесь в том, что когда пользователь задает обработчик входящего запроса (тип Handler), то должна быть возможность передать в этот обработчик ссылку на generic_request_handle_t<Extra_Data>. А если это не так, например, если пользователь забыл про свой Extra_Data и подсовывает обработчик для простого request_handle_t, то будет ошибка компиляции.

Ошибки компиляции в шаблонном C++ном коде не самое приятное чтиво и разбираться с ними то еще удовольствие. Поэтому хотелось поставить в код какой-то static_assert, который бы явно говорил программисту: у тебя Handler не дружит с твоим же собственным Extra_Data.

Однако сходу написать такой static_assert в свое время не получилось, поэтому в коде был оставлен FIXME: мол, когда-нибудь руки дойдут.

Вот, руки дошли. Попробовал написать такой static_assert.

Правда, там все нетривиально, есть две принципиально разных ситуации. В одной вроде как static_assert вырисовывается. В другой даже и не знаю, может да, может нет. Поэтому начал с обработки простой ситуации.

Написал, удовлетворил компилятор, попытался проверить как этот новый static_assert себя поведет.

Под катом два лога с сообщениями об ошибках компилятора GCC 9.4 в режиме C++14. Первый -- это старая версия с FIXME и без static_assert-а. Вторая -- новая версия без FIXME и со static_assert-ом.

Лично мне кажется, что разобраться с ошибкой в старой версии проще. Потому что благодаря static_assert-у на несчастного пользователя вываливается намного больше совершенно ненужной информации, разобраться в которой, на мой взгляд, гораздо сложнее.

Ну и да, видимо, этот FIXME из кода просто удалю и не буду делать никаких static_assert-ов. Потому что сложность кода растет, а пользы от этого никакой :(

Upd. Тема получила неожиданное продолжение.

Итак, вот как ругался компилятор раньше, если формат Handler-а не совпадал с типом первого аргумента (строку с ошибкой я специально жирным выделил):

In file included from test/router/easy_parser_path_to_tuple/main.cpp:14:
./restinio/router/easy_parser_router.hpp: In instantiation of ‘static auto restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<Target_Type, Subitems_Tuple>::invoke_handler(restinio::generic_request_handle_t<Extra_Data>&, Handler&&, typename restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<Target_Type, Subitems_Tuple>::base_type_t::result_type&) [with Extra_Data = test::ud_factory_t::data_t; Handler = const tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>&; Target_Type = std::tuple<int, int>; Subitems_Tuple = std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> >; restinio::generic_request_handle_t<Extra_Data> = std::shared_ptr<restinio::generic_request_t<test::ud_factory_t::data_t> >; typename restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<Target_Type, Subitems_Tuple>::base_type_t::result_type = std::tuple<int, int>]’:
./restinio/router/easy_parser_router.hpp:156:36:   required from ‘restinio::expected_t<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t> restinio::router::easy_parser_router::impl::actual_router_entry_t<Extra_Data, Producer, Handler>::try_handle(const actual_request_handle_t&, restinio::router::easy_parser_router::impl::target_path_holder_t&) const [with Extra_Data = test::ud_factory_t::data_t; Producer = restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >; Handler = tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>; restinio::expected_t<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t> = nonstd::expected_lite::expected<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t>; restinio::router::easy_parser_router::impl::actual_router_entry_t<Extra_Data, Producer, Handler>::actual_request_handle_t = std::shared_ptr<restinio::generic_request_t<test::ud_factory_t::data_t> >; restinio::router::easy_parser_router::impl::target_path_holder_t = restinio::router::impl::target_path_holder_t]’
./restinio/router/easy_parser_router.hpp:145:2:   required from here
./restinio/router/easy_parser_router.hpp:595:17: error: no match for call to ‘(const tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>) (restinio::generic_request_handle_t<test::ud_factory_t::data_t>&, restinio::easy_parser::impl::producer_tag<std::tuple<int, int> >::result_type&)’
  595 |   return handler( req, type );
      |          ~~~~~~~^~~~~~~~~~~~~
test/router/easy_parser_path_to_tuple/main.cpp:124:3: note: candidate: ‘template<class auto:32> tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>’
  124 |   [&]( const restinio::request_handle_t &, auto p ){
      |   ^
test/router/easy_parser_path_to_tuple/main.cpp:124:3: note:   template argument deduction/substitution failed:
In file included from test/router/easy_parser_path_to_tuple/main.cpp:14:
./restinio/router/easy_parser_router.hpp:595:17: note:   cannot convert ‘req’ (type ‘restinio::generic_request_handle_t<test::ud_factory_t::data_t>’ {aka ‘const std::shared_ptr<restinio::generic_request_t<test::ud_factory_t::data_t> >’}) to type ‘const request_handle_t&’ {aka ‘const std::shared_ptr<restinio::generic_request_t<restinio::no_extra_data_factory_t::data_t> >&’}
  595 |   return handler( req, type );
      |          ~~~~~~~^~~~~~~~~~~~~
./restinio/router/easy_parser_router.hpp: In instantiation of ‘restinio::expected_t<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t> restinio::router::easy_parser_router::impl::actual_router_entry_t<Extra_Data, Producer, Handler>::try_handle(const actual_request_handle_t&, restinio::router::easy_parser_router::impl::target_path_holder_t&) const [with Extra_Data = test::ud_factory_t::data_t; Producer = restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >; Handler = tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>; restinio::expected_t<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t> = nonstd::expected_lite::expected<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t>; restinio::router::easy_parser_router::impl::actual_router_entry_t<Extra_Data, Producer, Handler>::actual_request_handle_t = std::shared_ptr<restinio::generic_request_t<test::ud_factory_t::data_t> >; restinio::router::easy_parser_router::impl::target_path_holder_t = restinio::router::impl::target_path_holder_t]’:
./restinio/router/easy_parser_router.hpp:145:2:   required from here
./restinio/router/easy_parser_router.hpp:156:36: error: could not convert ‘restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >::invoke_handler<test::ud_factory_t::data_t, const tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>&>((* & req), ((const restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >*)this)->restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >::m_handler, (* & parse_result.nonstd::expected_lite::expected<std::tuple<int, int>, restinio::easy_parser::parse_error_t>::operator*()))’ from ‘void’ to ‘restinio::expected_t<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t>’ {aka ‘nonstd::expected_lite::expected<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t>’}
  156 |     return Producer::invoke_handler( req, m_handler, *parse_result );
      |            ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                    |
      |                                    void

А вот как он начал ругаться сейчас, со static_assert-ом:

In file included from test/router/easy_parser_path_to_tuple/main.cpp:14:
./restinio/router/easy_parser_router.hpp: In instantiation of ‘class restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >’:
/usr/include/c++/9/type_traits:1313:45:   required by substitution of ‘template<class _From1, class _To1, class> static std::true_type std::__is_convertible_helper<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >*, restinio::router::easy_parser_router::impl::router_entry_t<test::ud_factory_t::data_t>*, false>::__test<_From1, _To1, <template-parameter-1-3> >(int) [with _From1 = restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >*; _To1 = restinio::router::easy_parser_router::impl::router_entry_t<test::ud_factory_t::data_t>*; <template-parameter-1-3> = <missing>]’
/usr/include/c++/9/type_traits:1322:42:   required from ‘struct std::__is_convertible_helper<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >*, restinio::router::easy_parser_router::impl::router_entry_t<test::ud_factory_t::data_t>*, false>’
/usr/include/c++/9/type_traits:131:12:   recursively required from ‘struct std::__and_<std::is_convertible<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >*, restinio::router::easy_parser_router::impl::router_entry_t<test::ud_factory_t::data_t>*>, std::__not_<std::is_array<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> > > > >’
/usr/include/c++/9/type_traits:131:12:   required from ‘struct std::__and_<std::__and_<std::is_convertible<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >*, restinio::router::easy_parser_router::impl::router_entry_t<test::ud_factory_t::data_t>*>, std::__not_<std::is_array<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> > > > >, std::is_convertible<std::default_delete<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> > >, std::default_delete<restinio::router::easy_parser_router::impl::router_entry_t<test::ud_factory_t::data_t> > > >’
/usr/include/c++/9/type_traits:2048:11:   required by substitution of ‘template<class ... _Cond> using _Require = typename std::enable_if<std::__and_< <template-parameter-1-1> >::value>::type [with _Cond = {std::__and_<std::is_convertible<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >*, restinio::router::easy_parser_router::impl::router_entry_t<test::ud_factory_t::data_t>*>, std::__not_<std::is_array<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> > > > >, std::conditional<false, std::is_same<std::default_delete<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> > >, std::default_delete<restinio::router::easy_parser_router::impl::router_entry_t<test::ud_factory_t::data_t> > >, std::is_convertible<std::default_delete<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> > >, std::default_delete<restinio::router::easy_parser_router::impl::router_entry_t<test::ud_factory_t::data_t> > > >::type}]’
/usr/include/c++/9/bits/unique_ptr.h:266:44:   required by substitution of ‘template<class _Up, class _Ep, class> std::unique_ptr<restinio::router::easy_parser_router::impl::router_entry_t<test::ud_factory_t::data_t>, std::default_delete<restinio::router::easy_parser_router::impl::router_entry_t<test::ud_factory_t::data_t> > >::unique_ptr(std::unique_ptr<_Tp, _Dp>&&) [with _Up = restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >; _Ep = std::default_delete<restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> > >; <template-parameter-1-3> = <missing>]’
./restinio/router/easy_parser_router.hpp:1057:3:   required from ‘void restinio::router::generic_easy_parser_router_t<Extra_Data_Factory>::add_handler(Method_Matcher&&, Route_Producer&&, Handler&&) [with Method_Matcher = restinio::http_method_id_t; Route_Producer = restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >; Handler = tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>; Extra_Data_Factory = test::ud_factory_t]’
test/router/easy_parser_path_to_tuple/main.cpp:120:2:   required from ‘void tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]’
test/router/easy_parser_path_to_tuple/main.cpp:146:6:   required from here
./restinio/router/easy_parser_router.hpp:111:70: error: static assertion failed: Handler should be callable with generic_request_handle_t<Extra_Data>
  111 |    Producer::template handler_checker_metafunc<Handler, Extra_Data>::value,
      |                                                                      ^~~~~
./restinio/router/easy_parser_router.hpp: In instantiation of ‘static auto restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<Target_Type, Subitems_Tuple>::invoke_handler(restinio::generic_request_handle_t<Extra_Data>&, Handler&&, typename restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<Target_Type, Subitems_Tuple>::base_type_t::result_type&) [with Extra_Data = test::ud_factory_t::data_t; Handler = const tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>&; Target_Type = std::tuple<int, int>; Subitems_Tuple = std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> >; restinio::generic_request_handle_t<Extra_Data> = std::shared_ptr<restinio::generic_request_t<test::ud_factory_t::data_t> >; typename restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<Target_Type, Subitems_Tuple>::base_type_t::result_type = std::tuple<int, int>]’:
./restinio/router/easy_parser_router.hpp:154:36:   required from ‘restinio::expected_t<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t> restinio::router::easy_parser_router::impl::actual_router_entry_t<Extra_Data, Producer, Handler>::try_handle(const actual_request_handle_t&, restinio::router::easy_parser_router::impl::target_path_holder_t&) const [with Extra_Data = test::ud_factory_t::data_t; Producer = restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >; Handler = tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>; restinio::expected_t<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t> = nonstd::expected_lite::expected<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t>; restinio::router::easy_parser_router::impl::actual_router_entry_t<Extra_Data, Producer, Handler>::actual_request_handle_t = std::shared_ptr<restinio::generic_request_t<test::ud_factory_t::data_t> >; restinio::router::easy_parser_router::impl::target_path_holder_t = restinio::router::impl::target_path_holder_t]’
./restinio/router/easy_parser_router.hpp:143:2:   required from here
./restinio/router/easy_parser_router.hpp:593:17: error: no match for call to ‘(const tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>) (restinio::generic_request_handle_t<test::ud_factory_t::data_t>&, restinio::easy_parser::impl::producer_tag<std::tuple<int, int> >::result_type&)’
  593 |   return handler( req, type );
      |          ~~~~~~~^~~~~~~~~~~~~
test/router/easy_parser_path_to_tuple/main.cpp:124:3: note: candidate: ‘template<class auto:32> tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>’
  124 |   [&]( const restinio::request_handle_t &, auto p ){
      |   ^
test/router/easy_parser_path_to_tuple/main.cpp:124:3: note:   template argument deduction/substitution failed:
In file included from test/router/easy_parser_path_to_tuple/main.cpp:14:
./restinio/router/easy_parser_router.hpp:593:17: note:   cannot convert ‘req’ (type ‘restinio::generic_request_handle_t<test::ud_factory_t::data_t>’ {aka ‘const std::shared_ptr<restinio::generic_request_t<test::ud_factory_t::data_t> >’}) to type ‘const request_handle_t&’ {aka ‘const std::shared_ptr<restinio::generic_request_t<restinio::no_extra_data_factory_t::data_t> >&’}
  593 |   return handler( req, type );
      |          ~~~~~~~^~~~~~~~~~~~~
./restinio/router/easy_parser_router.hpp: In instantiation of ‘restinio::expected_t<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t> restinio::router::easy_parser_router::impl::actual_router_entry_t<Extra_Data, Producer, Handler>::try_handle(const actual_request_handle_t&, restinio::router::easy_parser_router::impl::target_path_holder_t&) const [with Extra_Data = test::ud_factory_t::data_t; Producer = restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >; Handler = tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>; restinio::expected_t<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t> = nonstd::expected_lite::expected<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t>; restinio::router::easy_parser_router::impl::actual_router_entry_t<Extra_Data, Producer, Handler>::actual_request_handle_t = std::shared_ptr<restinio::generic_request_t<test::ud_factory_t::data_t> >; restinio::router::easy_parser_router::impl::target_path_holder_t = restinio::router::impl::target_path_holder_t]’:
./restinio/router/easy_parser_router.hpp:143:2:   required from here
./restinio/router/easy_parser_router.hpp:154:36: error: could not convert ‘restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >::invoke_handler<test::ud_factory_t::data_t, const tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)>&>((* & req), ((const restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >*)this)->restinio::router::easy_parser_router::impl::actual_router_entry_t<test::ud_factory_t::data_t, restinio::router::easy_parser_router::impl::path_to_tuple_producer_t<std::tuple<int, int>, std::tuple<restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<15>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 0>, restinio::router::easy_parser_router::impl::special_exact_fixed_size_fragment_clause_t<11>, restinio::router::easy_parser_router::impl::special_produce_tuple_item_clause_t<restinio::easy_parser::impl::non_negative_decimal_number_producer_t<int>, 1> > >, tc_two_parameters() [with Router = restinio::router::generic_easy_parser_router_t<test::ud_factory_t>]::<lambda(const request_handle_t&, auto:32)> >::m_handler, (* & parse_result.nonstd::expected_lite::expected<std::tuple<int, int>, restinio::easy_parser::parse_error_t>::operator*()))’ from ‘void’ to ‘restinio::expected_t<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t>’ {aka ‘nonstd::expected_lite::expected<restinio::request_handling_status_t, restinio::router::easy_parser_router::impl::no_match_t>’}
  154 |     return Producer::invoke_handler( req, m_handler, *parse_result );
      |            ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                    |
      |                                    void

Ну и, для истории, пара фрагментов кода, который был написан для получения этого результата. На качество кода можно не обращать внимания, это самый первый черновик, задача была получить работающее решение, которое затем уже можно было бы причесать и облагородить:

templatetypename Extra_Data, typename Producer, typename Handler >
class actual_router_entry_t : public router_entry_t< Extra_Data >
{
   static_assert(
         Producer::template handler_checker_metafunc<Handler, Extra_Data>::value,
         "Handler should be callable with generic_request_handle_t<Extra_Data>" );
...
};
...
template<
   typename Handler,
   typename Extra_Data,
   typename Tuple,
   typename = restinio::utils::metaprogramming::void_t<> >
struct is_valid_handler_for_extra_data_1 : public std::false_type {};

template<
      typename Handler,
      typename Extra_Data,
      typename Tuple >
struct is_valid_handler_for_extra_data_1<
      Handler,
      Extra_Data,
      Tuple,
      restinio::utils::metaprogramming::void_t<
         decltype(
            std::declval<Handler &>()(
               std::declval<const generic_request_handle_t<Extra_Data> &>(),
               std::declval<Tuple &>()
            )
         )
      >
   > : public std::true_type {};

template<
   typename Target_Type,
   typename Subitems_Tuple >
class path_to_tuple_producer_t
   :  public ep::impl::produce_t< Target_Type, Subitems_Tuple >
{
   using base_type_t = ep::impl::produce_t< Target_Type, Subitems_Tuple >;

public:
   using base_type_t::base_type_t;

   templatetypename Handler, typename Extra_Data >
   using handler_checker_metafunc = is_valid_handler_for_extra_data_1<
         Handler,
         Extra_Data,
         typename base_type_t::result_type >;

Комментариев нет: