templates - C++ Multiple sets of variadic function arguments -
i'm trying optimize low level , used function in compute intensive application. let's have following type :
template<typename t, int n> class elem {...}; i'd write function called such :
template<typename t, int n> void func(const elem<t, n> & ... /*n elements*/, elem<t, n> & ... /* n elements*/) i'm looking approach can sure compilers able remove temporary introduced function signature.
the elements typically elements taken different places of vector/array. e.g. :
elem<float, 3> inputs[10]; elem<float, 3> outputs[10]; ... func(input[4], input[2], input[9], output[6], output[8], output[1]); the answer might initializer lists fear might have overhead...
nb : indirection indexes above compile-time computed function , in short ranges.
edit
in fact, i'd :
template<typename... t, int n> void func(const elem<t, n>&... inputs, const elem<t, n>&... outputs) { static_assert(sizeof...(inputs) == n, "invalid number of arguments"); static_assert(sizeof...(outputs) == n, "invalid number of arguments"); static_assert(std::is_same<std::integral_constant<int n>...>::value, "invalid arguments"); } but can't have code compile on vs2017. answer can c++17.
i'd write function called such :
template<typename t, int n> void func(const elem<t, n> & ... /*n elements*/, elem<t, n> & ... /* n elements*/) as far know, ask isn't easy express available language.
the best can imagine, write func() function follows
template <typename ... es> typename std::enable_if<checkelems<es...>::value>::type func (es & ... es) { using type = typename checkelems<es ...>::type; // former t constexpr std::size_t num { sizeof...(es) >> 1 }; // former n // ... } where func() receives list (es & ... es) of arguments , function sfinae enabled if relative list of types (es ...) satisfy list of requirements implemented in custom type-traits checkelems (see following example).
so following checkelems check that:
- there @ least argument type
- the first argument in form
elem<t, n> const - the number of argument type
2 * n - the first
ntypes equal each other - the following
ntypes equal each other - adding
constfollowingntypes, equal firstn - without adding
const, followingntypes different firstn
inside func() you're able use type (see example), t type in elem<t, n>, , num, n value in elem<t, n>.
you can checks don't know if it's idea.
a compilable example
#include <tuple> #include <type_traits> template<typename t, std::size_t n> struct elem {}; template <typename> struct extrelem; template <typename t, std::size_t n> struct extrelem<elem<t, n> const> { using type = t; static constexpr std::size_t num { n }; }; template <std::size_t, std::size_t, typename ...> struct extrtypes; template <std::size_t skip, std::size_t num, typename ... es, typename t0, typename ... ts> struct extrtypes<skip, num, std::tuple<es...>, t0, ts...> { using type = typename extrtypes< skip-1u, num, std::tuple<es...>, ts...>::type; }; template <std::size_t num, typename ... es, typename t0, typename ... ts> struct extrtypes<0u, num, std::tuple<es...>, t0, ts...> { using type = typename extrtypes< 0u, num-1u, std::tuple<es..., t0>, ts...>::type; }; template <typename ... es, typename t0, typename ... ts> struct extrtypes<0u, 0u, std::tuple<es...>, t0, ts...> { using type = std::tuple<es...>; }; template <typename ... es> struct extrtypes<0u, 0u, std::tuple<es...>> { using type = std::tuple<es...>; }; template <typename> struct sameconttypes : public std::false_type { }; template <template <typename ...> class c, typename t0, typename ... ts> struct sameconttypes<c<t0, ts...>> : public std::is_same<c<t0, ts...>, c<ts..., t0>> { }; template <typename e0, typename ... es> struct checkelems { static constexpr std::size_t num { extrelem<e0>::num }; using type = typename extrelem<e0>::type; using lt1 = typename extrtypes<0u, num, std::tuple<>, e0, es...>::type; using lt2 = typename extrtypes<num, num, std::tuple<>, e0, es...>::type; static constexpr bool value { ( (num << 1) == 1u + sizeof...(es) ) && sameconttypes<lt1>::value && sameconttypes<lt2>::value && (true == std::is_same<e0, typename std::tuple_element<0u, lt2>::type const>::value) && (false == std::is_same<e0, typename std::tuple_element<0u, lt2>::type>::value) }; }; template <typename ... es> typename std::enable_if<checkelems<es...>::value>::type func (es & ... es) { using type = typename checkelems<es ...>::type; // former t constexpr std::size_t num { sizeof...(es) >> 1 }; // former n // ... } int main() { elem<int, 3> ei3; elem<int, 4> ei4; elem<int, 3> const eci3; elem<int, 4> const eci4; func(eci3, eci3, eci3, ei3, ei3, ei3); // compile //func(eci3, eci3, eci3, ei3, eci3, ei3); // compilation error //func(eci3, eci3, eci3, ei3, ei3, ei4); // compilation error //func(eci3, eci3, eci4, ei3, ei3, ei3); // compilation error //func(eci4, eci4, eci4, ei4, ei4, ei4); // compilation error //func(eci4, eci4, eci4, eci4, ei4, ei4, ei4); // compilation error func(eci4, eci4, eci4, eci4, ei4, ei4, ei4, ei4); // compile }
Comments
Post a Comment