diff --git a/core/include/gnuradio-4.0/Block.hpp b/core/include/gnuradio-4.0/Block.hpp index 3b2c83423..cf3a2d5b9 100644 --- a/core/include/gnuradio-4.0/Block.hpp +++ b/core/include/gnuradio-4.0/Block.hpp @@ -1933,6 +1933,26 @@ struct BlockParameters : meta::typelist { static constexpr /*vir::fixed_string*/ auto toString() { return detail::encodeListOfTypes(); } }; +template +inline int registerBlock(auto& registerInstance) { + using namespace vir::literals; + constexpr auto name = vir::refl::class_name; + constexpr auto longname = vir::refl::type_name; + if constexpr (name != longname) { + constexpr auto tmpl = longname.substring(name.size + 1_cw, longname.size - 2_cw - name.size); + registerInstance.template addBlockType(name, tmpl); + } else { + registerInstance.template addBlockType(name, {}); + } + return 0; +} + +template +inline int registerBlock(auto& registerInstance) { + registerBlock(registerInstance); + return registerBlock(registerInstance); +} + /** * This function (and overloads) can be used to register a block with * the block registry to be used for runtime instantiation of blocks @@ -1945,15 +1965,16 @@ struct BlockParameters : meta::typelist { * set these to the values of NTTPs you want to register * - TBlockParameters -- types that the block can be instantiated with */ -template typename TBlock, typename... TBlockParameters, typename TRegisterInstance> -inline constexpr int registerBlock(TRegisterInstance& registerInstance) { - auto addBlockType = [&] { - using ThisBlock = TBlock; - static_assert(!meta::is_instantiation_of); - registerInstance.template addBlockType(vir::refl::class_name>, vir::refl::type_name); - }; - ((addBlockType.template operator()()), ...); - return {}; +template typename TBlock, typename TBlockParameter0, typename... TBlockParameters> +inline int registerBlock(auto& registerInstance) { + using List0 = std::conditional_t, TBlockParameter0, BlockParameters>; + using ThisBlock = typename List0::template apply; + registerInstance.template addBlockType(vir::refl::class_name, List0::toString()); + if constexpr (sizeof...(TBlockParameters) != 0) { + return registerBlock(registerInstance); + } else { + return {}; + } } /** @@ -1965,44 +1986,28 @@ inline constexpr int registerBlock(TRegisterInstance& registerInstance) { * - TBlock -- the block class template with two template parameters * - Tuple1 -- a std::tuple containing the types for the first template parameter of TBlock * - Tuple2 -- a std::tuple containing the types for the second template parameter of TBlock + * - optionally more Tuples * * This function iterates over all combinations of the types in Tuple1 and Tuple2, * instantiates TBlock with each combination, and registers the block with the registry. */ -template typename TBlock, typename Tuple1, typename Tuple2, typename TRegisterInstance> -inline constexpr int registerBlockTT(TRegisterInstance& registerInstance) { - auto addBlockType = [&] { - using ThisBlock = TBlock; - registerInstance.template addBlockType( // - vir::refl::class_name, vir::refl::type_name + vir::fixed_string<",">() + vir::refl::type_name); - }; - - std::apply( - [&](T1...) { // iterate over first type - std::apply( - [&](T2...) { // iterate over second type - (([&]() { ((addBlockType.template operator()()), ...); }.template operator()()), ...); - }, - Tuple2{}); - }, - Tuple1{}); - +template typename TBlock, typename... Tuples> +inline constexpr int registerBlockTT(auto& registerInstance) { + meta::outer_product...>::for_each([&](std::size_t, Types*) { registerBlock>(registerInstance); }); return {}; } -template typename TBlock, typename TBlockParameter0, typename... TBlockParameters> -inline int registerBlock(auto& registerInstance) { - using ThisBlock = TBlock, typename TBlockParameter0::template at<1>>; - static_assert(meta::is_instantiation_of); - static_assert(TBlockParameter0::size == 2); - registerInstance.template addBlockType(vir::refl::class_name, TBlockParameter0::toString()); - if constexpr (sizeof...(TBlockParameters) != 0) { - return registerBlock(registerInstance); - } else { - return {}; - } -} - +// FIXME: the following are inconsistent in how they specialize the template. Multiple types can be given, resulting in +// multiple specializations for each type. If the template requires more than one type then the types must be passed as +// a typelist (BlockParameters) instead. NTTP arguments, however, can only be given exactly as many as there are NTTPs +// in the template. Also the order is "messed up". +// Suggestion: +// template struct Nttp { static constexpr value = X; }; +// then use e.g. +// - BlockParameters> +// - BlockParameters, double, Nttp, Nttp> +// Sadly, we can't remove any of the following overloads because we can't generalize the template template parameter +// (yet). And in principle, there's always another overload missing. template typename TBlock, auto Value0, typename... TBlockParameters, typename TRegisterInstance> inline constexpr int registerBlock(TRegisterInstance& registerInstance) { auto addBlockType = [&] { diff --git a/meta/include/gnuradio-4.0/meta/typelist.hpp b/meta/include/gnuradio-4.0/meta/typelist.hpp index 0bb87b1dd..5f0b959f7 100644 --- a/meta/include/gnuradio-4.0/meta/typelist.hpp +++ b/meta/include/gnuradio-4.0/meta/typelist.hpp @@ -67,6 +67,47 @@ struct concat_impl { template using concat = typename detail::concat_impl::type; +// outer_product //////// +namespace detail { +template +struct outer_product_impl; + +template +struct outer_product_impl> { + using type = typelist; +}; + +template +struct outer_product_impl, typelist> { + using type = typelist<>; +}; + +template +struct outer_product_impl, typelist> { + using type = typelist...>; +}; + +template +struct outer_product_impl, typelist> { + using type = typelist..., typelist...>; +}; + +template +struct outer_product_impl, typelist> { + using tmp = typename outer_product_impl, typelist>::type; + using type = concat..., typelist..., typelist...>, tmp>; +}; + +template +requires(sizeof...(More) > 0) +struct outer_product_impl { + using type = typename outer_product_impl::type, More...>::type; +}; +} // namespace detail + +template +using outer_product = typename detail::outer_product_impl::type; + // split_at, left_of, right_of //////////////// namespace detail { template