An easy way in C++11 is:
template <std::size_t N>
void func(const std::array<const char*, N>& cstrings,
const std::array<int, N>& ints
const std::array<char, N>& chars);
And so you may use it:
func({ "aa","sd","zzz"}, {123, 13, 3} , {'w', 'a', 'x'});
If you want to use the same syntax, it is more verbose and use SFINAE:
it falls back to call the version with std::array
as it is more convenient to implement
#include <cstdint>
#include <array>
#include <tuple>
#include <type_traits>
#if 1 // Not in C++11
template <std::size_t ...> struct index_sequence {};
template <std::size_t I, std::size_t ...Is>
struct make_index_sequence : make_index_sequence < I - 1, I - 1, Is... > {};
template <std::size_t ... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> {
typedef index_sequence<Is...> type;
};
#endif
template <std::size_t N>
void func(const std::array<const char*, N>& cstrings,
const std::array<int, N>& ints
const std::array<char, N>& chars)
{
// Add your code here
}
namespace detail
{
template <typename T, typename SEQ, typename SEQ2> struct helper_split3;
template <typename ... Ts, std::size_t ... Is, std::size_t ... Is2>
struct helper_split3<std::tuple<Ts...>, index_sequence<Is...>, index_sequence<Is2...> >
{
typedef std::tuple<typename std::tuple_element<Is, std::tuple<Ts...> >::type...> First;
typedef std::tuple<typename std::tuple_element<sizeof...(Is) + Is, std::tuple<Ts...> >::type...> Middle;
typedef std::tuple<typename std::tuple_element<2 * sizeof...(Is) + Is2, std::tuple<Ts...> >::type...> Last;
};
template <typename T, typename ... Ts> struct are_same : std::true_type {};
template <typename T, typename Tail, typename ... Ts>
struct are_same<T, Tail, Ts...> :
std::conditional<std::is_same<T, Tail>::value && are_same<T, Ts...>::value,
std::true_type, std::false_type>::type {};
template <typename T, typename Tuple> struct are_same_in_tuple;
template <typename T, typename ... Ts>
struct are_same_in_tuple<T, std::tuple<Ts...>> : are_same<T, Ts...> {};
template<typename ... Ts>
struct func_trait
{
typedef helper_split3<std::tuple<Ts...>,
typename make_index_sequence<sizeof...(Ts) / 3>::type,
typename make_index_sequence<sizeof...(Ts) - 2 * (sizeof...(Ts) / 3)>::type>
helper;
static const bool value = (sizeof...(Ts) % 3 == 0)
&& are_same_in_tuple<const char*, typename helper::First>::value
&& are_same_in_tuple<int, typename helper::Middle>::value
&& are_same_in_tuple<char, typename helper::Last>::value;
};
template <typename ... Ts, std::size_t ... Is>
void func(std::tuple<Ts...>&& t, index_sequence<Is...>)
{
constexpr std::size_t N = sizeof...(Ts);
::func<N>(std::array<const char*, N>({std::get<Is>(t)...}),
std::array<int, N>({std::get<sizeof...(Is) + Is>(t)...}),
std::array<char, N>({std::get<2 * sizeof...(Is) + Is>(t)...}));
}
} // namespace detail
template <typename ... Ts>
typename std::enable_if<detail::func_trait<Ts...>::value, void>::type
func(Ts...args)
{
detail::func(std::tie(args...), make_index_sequence<sizeof...(Ts) / 3>());
}