Create repeated declaration
This is easy with Boost.Mp11:
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/list.hpp>
namespace mp11 = boost::mp11;
template<class... Args>
using make_fn = std::function<void(Args...)>;
using TypeList = mp11::mp_repeat_c<mp11::mp_list<double>, 8>;
using FunType = mp11::mp_apply<make_fn, TypeList>;
using DataType = mp11::mp_apply<std::tuple, TypeList>;
An alternative C++14 solution without Boost:
template<template<class...> class Fn, class T, std::size_t n>
struct apply_repeat {
template<std::size_t... is>
static Fn<decltype(is, T{})...>
get_type(std::index_sequence<is...>);
using type = decltype(get_type(std::make_index_sequence<n>{}));
};
template<class... Args>
using make_fn = std::function<void(Args...)>;
using FunType = typename apply_repeat<make_fn, double, 8>::type;
using DataType = typename apply_repeat<std::tuple, double, 8>::type;
This solution requires a default constructible T
. This requirement is satisfied for double
.
To lift this requirement we can use type_identity
wrapper (will be part of C++20):
template<class T>
struct type_identity {
using type = T;
};
template<template<class...> class Fn, class T, std::size_t n>
struct apply_repeat {
template<std::size_t... is>
static Fn<typename decltype(is, type_identity<T>{})::type...>
get_type(std::index_sequence<is...>);
using type = decltype(get_type(std::make_index_sequence<n>{}));
};
No need to drag Boost into this, here is C++11 solution:
#include <cstdint>
template<std::size_t N,typename R,typename T, typename...Args>
struct function_replicator{
//Add an extra T that will be packed with Args... in the nested template.
using type = typename function_replicator<N-1,R,T,T,Args...>::type;
};
template<typename R,typename T, typename...Args>
struct function_replicator<0,R,T,Args...>{
//Args... holds N Ts
using type = R(Args...);
};
template<std::size_t N,template<typename...CArgs>class Container,typename T, typename...Args>
struct container_replicator{
using type = typename container_replicator<N-1,Container,T,T,Args...>::type;
};
template<template<typename...CArgs>class Container,typename T, typename...Args>
struct container_replicator<0,Container,T,Args...>{
using type = Container<Args...>;
};
#include <tuple>
#include <functional>
// Feel free to make them more general.
template<std::size_t N>
using function_def = std::function<typename function_replicator<N,void,double>::type>;
template<std::size_t N>
using tuple_def = typename container_replicator<N,std::tuple,double>::type;
#include <type_traits>
int main(){
//Keeping it C++11
static_assert(std::is_same<function_def<3>,std::function<void(double,double,double)>>::value,"");
static_assert(std::is_same<tuple_def<3>,std::tuple<double,double, double>>::value,"");
}
Here is pure C++ solution without Boost or Macros, just variadic templates:
#include <tuple>
#include <utility>
#include <functional>
// tuple
template <typename T, std::size_t ... Is>
constexpr auto gft_helper (std::index_sequence<Is...> const &)
-> decltype(std::make_tuple( (Is, std::declval<T>())... ));
template <typename T, std::size_t N>
constexpr auto get_fixed_tuple ()
-> decltype(gft_helper<T>(std::make_index_sequence<N>{}));
template <typename T, std::size_t N>
using tuple_fixed_type = decltype(get_fixed_tuple<T, N>());
// function
template <typename T>
constexpr auto getType(int, T&& t)
-> typename std::decay<T>::type;
template <typename T, std::size_t ... Is>
constexpr auto gff_helper (std::index_sequence<Is...> const &)
-> std::function<void( decltype(getType(Is, std::declval<T>()))...)>;
template <typename T, std::size_t N>
constexpr auto get_fixed_function ()
-> decltype(gff_helper<T>(std::make_index_sequence<N>{}));
template <typename T, std::size_t N>
using function_fixed_type = decltype(get_fixed_function<T, N>());
int main()
{
using FunType = function_fixed_type<double,4>;
using DataType = tuple_fixed_type<double,4>;
static_assert(std::is_same<DataType, std::tuple<double, double, double, double>>{} );
static_assert(std::is_same<FunType, std::function<void(double, double, double, double)>>{} );
}