Pat*_*ryk 5 c++ templates type-traits c++11 c++14
我有以下代码片段,我struct quick
用模板化static
方法定义random
了一些特殊化:
(我使用function_traits
其他SO答案.附在底部供参考.)
struct quick
{
template <typename T>
static T random();
template <typename F>
static void check(F f)
{
constexpr auto arity = function_traits<F>::arity; // easy :)
std::cout << arity << std::endl;
typedef typename function_traits<F>::template arg<0>::type type0; // easy:)
// how to get all types of all F's parameters?
}
};
template <>
std::string quick::random<std::string>()
{
return std::string("test");
}
template <>
int quick::random<int>()
{
return 1;
}
Run Code Online (Sandbox Code Playgroud)
我想获取所有类型F
的参数,check
以便我可以生成tuple
随机条目(基于我的random
方法特化).
像这样:
auto t0 = std::make_tuple(quick::random<AllTypes>()...); //pseudo code
auto t =
std::make_tuple(quick::random <
function_traits<F>::template arg<std::make_index_sequence<arity>>::type...
>
()...
);
Run Code Online (Sandbox Code Playgroud)
我尝试过类似的东西:
template<typename F, typename ...TIdxs>
using ArgTypes = typename function_traits<F>::template arg<TIdxs>::type...;
// ...
// inside check
typedef ArgTypes<F, std::make_index_sequence<arity>> types;
Run Code Online (Sandbox Code Playgroud)
但悲惨地失败了:
main.cpp:80:72: error: expected ‘;’ before ‘...’ token
using ArgTypes = typename function_traits<F>::template arg<TIdxs>::type...;
^
main.cpp: In static member function ‘static void quick::check(F, D)’:
main.cpp:98:15: error: ‘ArgTypes’ does not name a type
typedef ArgTypes<F, std::make_index_sequence<arity>> types;
Run Code Online (Sandbox Code Playgroud)
我已经使用function traits
了这个 SO答案的实用工具.
template <typename T>
struct function_traits : function_traits<decltype(&T::operator())>
{};
// For generic types, directly use the result of the signature of its 'operator()'
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
enum { arity = sizeof...(Args) };
// arity is the number of arguments.
typedef ReturnType result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
// the i-th argument is equivalent to the i-th tuple element of a tuple
// composed of those arguments.
};
};
Run Code Online (Sandbox Code Playgroud)
请注意function_traits
,您已经拥有所有参数类型.你所要做的就是揭露它们:
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
enum { arity = sizeof...(Args) };
using result_type = ReturnType;
using all_args = std::tuple<Args...>; // <-- add this
template <size_t i> // <-- consider making this an alias template
using arg = std::tuple_element_t<i, all_args>;
};
Run Code Online (Sandbox Code Playgroud)
而现在,获取所有函数参数只是function_traits<F>::all_args
.
如果您不想更改function_traits
,我们只需添加外部元函数:
template <class F, class = std::make_index_sequence<function_traits<F>::arity>>
struct all_args;
template <class F, size_t... Is>
struct all_args<F, std::index_sequence<Is...>> {
using type = std::tuple<typename function_traits<F>::template arg<Is>::type...>;
};
template <class F>
using all_args_t = typename all_args<F>::type;
Run Code Online (Sandbox Code Playgroud)
max*_*x66 -1
不确定这就是您想要的但是...quick
按以下方式修改怎么样?
struct quick
{
template <typename T>
static T random();
template<typename F, std::size_t I>
using ArgTypes = typename function_traits<F>::template arg<I>::type;
template<typename F, std::size_t ... Is>
using ArgTuple = std::tuple< ArgTypes<F, Is>... >;
template <typename F, std::size_t ... Is>
static ArgTuple<F, Is...> makeArgTuple ()
{ return make_tuple(quick::random<Is>()...); }
template <typename F>
static void check(F f)
{
constexpr auto arity = function_traits<F>::arity; // easy :)
std::cout << arity << std::endl;
typedef typename function_traits<F>::template arg<0>::type type0; // easy:)
auto t = ArgTuple<F, std::make_index_sequence<arity>::type> ();
auto t2 = makeArgTuple<F, std::make_index_sequence<arity>::type>();
}
};
Run Code Online (Sandbox Code Playgroud)
你错误地将typename
s传递TIdxs
给arg
; arg
需要一个std::size_t
.
考虑到std::make_index_sequence
它是 C++14 功能(但在 C++11 中创建它也很容易)。
ps:抱歉我的英语不好。