[英]How to pass std::index_sequence param to an nested-template struct according to function traits
这是我的简单代码,它确实有效(我将单个 integer 传递给argument
):
#include <iostream>
#include <tuple>
#include <string>
#include "boost/variant.hpp"
using TObjList = std::vector<boost::variant<std::string, int>>;
template<typename> struct FTrait;
template<typename R, typename... A> struct FTrait<R(A...)> {
using RetType = R;
using ArgsTuple = std::tuple<A...>;
static constexpr std::size_t arity = sizeof...(A);
template<size_t N> struct argument {
static_assert( N < arity , "error: invalid argument index");
typedef typename std::tuple_element_t<N, std::tuple<A...>> type;
};
};
void Show(const std::string& s, int a) {
std::cout << s << "\n" << a << "\n";
}
int main() {
TObjList list;
list.emplace_back("hello");
list.emplace_back(567);
Show(boost::get<FTrait<decltype(Show)>::argument<0>::type>(list[0]),
boost::get<FTrait<decltype(Show)>::argument<1>::type>(list[1]));
}
但是下面的代码不起作用(也许我将一个序列传递给了argument
):
#include <iostream>
#include <tuple>
#include <string>
#include "boost/variant.hpp"
using TObjList = std::vector<boost::variant<std::string, int>>;
template<typename> struct FTrait;
template<typename R, typename... A> struct FTrait<R(A...)> {
using RetType = R;
using ArgsTuple = std::tuple<A...>;
static constexpr std::size_t arity = sizeof...(A);
template<size_t N> struct argument {
static_assert( N < arity , "error: invalid argument index");
typedef typename std::tuple_element_t<N, std::tuple<A...>> type;
};
};
// here is new code
template<typename T> struct ConvertOne {
T operator () (const TObjList& List, size_t Index) {
if ( Index < List.size() ) {
return boost::get<T>(List[Index]);
}
}
};
template<typename F, size_t... Index>
void MyCall(const F& Func, const TObjList& List, const std::index_sequence<Index...>&) {
// This code not work:
Func(ConvertOne<typename FTrait<F>::argument<Index>::type>{}(List, Index)...);
// These code would work:
// using ArgsTuple = typename FTrait<F>::ArgsTuple;
// Func(ConvertOne<std::decay_t<typename std::tuple_element_t<Index, ArgsTuple>>>{}(List, Index)...);
}
// new code done
void Show(const std::string& s, int a) {
std::cout << s << "\n" << a << "\n";
}
int main() {
TObjList list;
list.emplace_back("hello");
list.emplace_back(567);
// new invoke
MyCall(Show, list, std::make_index_sequence<FTrait<decltype(Show)>::arity>{});
}
此代码会引发编译错误:
ftrait.cpp: In function ‘void MyCall(const F&, const TObjList&, std::index_sequence<Index ...>&)’:
ftrait.cpp:34:62: error: template argument 1 is invalid
Func(ConvertOne<typename FTrait<F>::argument<Index>::type>{}(List, Index)...);
我希望使用std::index_sequence
和function_traits
让程序自动识别一个 function 的参数类型和数量,比如std::tuple_element<Index, ArgsTuple>::type
。 boost::function_traits
不能满足我,所以我尝试自己实现。 我应该怎么办? 谢谢:)
在您的情况下, typename FTrait<F>::argument<0>::type
是const std::string&
。
std::get<const std::string&>(list[0])
不会编译std::get<std::string>(list[0])
。 它可以用std::decay
解决:
template<typename F, size_t... Index>
void MyCall(const F& Func, const TObjList& List, const std::index_sequence<Index...>&)
{
Func(ConvertOne<
typename std::decay<
typename FTrait<F>::template argument<Index>::type
>::type
>{}(List, Index)...);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.