c++ - Variadic template argument within template template parameter in a partial specialization -
i trying develop generic code can select different containers types (std::vector, std::map, other), , perform operations on container wrapper, got stuck following code:
enum class econtainnertype { econtainnertype_normal, econtainnertype_or, econtainnertype_and }; // base declaration template<econtainnertype, template<class ... > class containertype, class ... argtype > struct conditioncontainnertype { }; // partial specialization template< template<class ... > class containertype, class ... argtype > struct conditioncontainnertype<econtainnertype::econtainnertype_or, containertype<argtype ... >, argtype ...> { }; int main() { return 0; } the variadic template template argument not compile, , error:
main.cpp:33:108: error: wrong number of template arguments (2, should 3) struct conditioncontainnertype<econtainnertype::econtainnertype_or,typename containertype<argtype>, argtype> ^ main.cpp:29:8: error: provided 'template<econtainnertype <anonymous>, template<class> class containertype, class argtype> struct conditioncontainnertype' struct conditioncontainnertype goal:
the main goal of implementation perform kind of operation of classification (or, and, xor), operation performed on element compared against generic container.
the operation type defined enum class, , partial specialization selected action.
so, if have set {a,b,c,d,e} , fill set specific combination of elements say: generic_container<operation_type,generic_set_element> want generic conditional container perform action selected "operation type". if element x compared against set, generic container can perform preselected action on x element.
the problem cannot specialize template-template parameter template-template parameter given template arguments, forcing:
containertype<args...> to match:
template <typename...> class basecontainertype because no longer template template argument. instead, plain containertype name need used here, without <args...> part:
// base declaration template <template <typename...> class containertype> struct conditioncontainnertype { }; // partial specialization two-parameter template template parameter template <template <typename, typename> class containertype> struct conditioncontainnertype<containertype> { }; you can, however, specialize template type template-template parameter filled arguments (even expanded parameter pack), goes follows:
// base declaration template <econtainnertype, typename containertype, typename... args> // ^^^^^^^^^^^^^^^^^^^^^^^ normal type here struct conditioncontainnertype { }; // partial specialization template <template <typename...> class containertype, typename... args> // ^^^^^^^^ template here struct conditioncontainnertype<econtainnertype::econtainnertype_or, containertype<args...>, // ^^^^^^^ expanded parameter pack args...> { }; or without trailing parameter pack:
template <template <typename...> class containertype, typename... args> struct conditioncontainnertype<econtainnertype::econtainnertype_or, containertype<args...>> { }; as specialize templated containers std::vector<t, a> take 2 parameters: type t , allocator a:
template <template <typename, typename> class containertype, typename t, typename a> struct conditioncontainnertype<econtainnertype::econtainnertype_or, containertype<t, a>, t> { }; tests:
int main() { // base, , not match or conditioncontainnertype<econtainnertype::econtainnertype_and , mycontainer<int> , int>{}; // specialized, or , parameter pack matches conditioncontainnertype<econtainnertype::econtainnertype_or , mycontainer<int> , int>{}; // base, or matches, parameters packs not conditioncontainnertype<econtainnertype::econtainnertype_or , mycontainer<float> , int>{}; // vector, or , parameter pack matches conditioncontainnertype<econtainnertype::econtainnertype_or , std::vector<int> , int>{}; // or , no parameter-pack conditioncontainnertype<econtainnertype::econtainnertype_or , std::vector<int>>{}; } if otherwise aim specialize base declaration depending on concrete container type (std::vector, std::map), can follows:
// base declaration template <econtainnertype, template <typename...> class containertype> struct conditioncontainnertype { }; // partial specialization std::vector template <> struct conditioncontainnertype<econtainnertype::econtainnertype_or, std::vector> // ^^^^^^^^^^^ { }; // partial specialization std::map template <> struct conditioncontainnertype<econtainnertype::econtainnertype_and, std::map> // ^^^^^^^^ { }; tests:
int main() { // first specialization conditioncontainnertype<econtainnertype::econtainnertype_or, std::vector>{}; // second specialization conditioncontainnertype<econtainnertype::econtainnertype_and, std::map>{}; }
Comments
Post a Comment