我有一个名为的函数_push,它可以处理不同的参数,包括元组,并且应该返回推送元素的数量.
例如,_push(5)应该在堆栈上推送'5'(lua的堆栈)并返回1(因为推送了一个值),同时_push(std::make_tuple(5, "hello"))应该按'5'和'hello'并返回2.
我不能简单地替换它_push(5, "hello")因为我有时使用_push(foo())并且我想允许foo()返回一个元组.
无论如何,我无法使它与元组一起工作:
template<typename... Args, int N = sizeof...(Args)>
int _push(const std::tuple<Args...>& t, typename std::enable_if<(N >= 1)>::type* = nullptr) {
return _push<Args...,N-1>(t) + _push(std::get<N-1>(t));
}
template<typename... Args, int N = sizeof...(Args)>
int _push(const std::tuple<Args...>& t, typename std::enable_if<(N == 0)>::type* = nullptr) {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
假设你想推动一个tuple<int,bool>.这就是我期望它的工作方式:
_push<{int,bool}, 2> 被称为(第一个定义)_push<{int,bool}, 1> 被称为(第一个定义)_push<{int,bool}, 0> 被称为(第二个定义)但是对于g ++ 4.5(我唯一支持可变参数模板的编译器),我得到一个错误_push<Args...,N-1>(t)(第3行),说它无法找到匹配的函数来调用(没有任何进一步的细节).我尝试没有"...",但我得到另一个错误,说参数包没有扩展.
我怎样才能解决这个问题?
PS:我知道你可以使用模板结构来实现这一点(这实际上就是我以前做过的事情),但我想知道如何用一个函数来做
PS 2:PS2解决了,感谢GMan
I don't have a compiler to test any of this, so you'll have to report any issues.
以下应该允许您遍历调用函数的元组.它基于你的逻辑,只有一些小的改变.(N是一个std::size_t,它是允许Args(和Func)在进一步调用中推导出的第一个参数,它只调用某个函数而不是执行特定任务).没什么太激烈的:
namespace detail
{
// just to keep things concise and readable
#define ENABLE_IF(x) typename std::enable_if<(x)>::type
// recursive case
template <std::size_t N, typename... Args, typename Func>
ENABLE_IF(N >= 1) iterate(const std::tuple<Args...>& pTuple, Func& pFunc)
{
pFunc(std::get<N - 1>(pTuple));
iterate<N - 1>(pTuple, pFunc);
}
// base case
template <std::size_t N, typename... Args, typename Func>
ENABLE_IF(N == 0) iterate(const std::tuple<Args...>&, Func&)
{
// done
}
}
// iterate tuple
template <typename... Args, typename Func>
Func iterate(const std::tuple<Args...>& pTuple, Func pFunc)
{
detail::iterate<sizeof...(Args)>(pTuple, pFunc);
return pFunc;
}
Run Code Online (Sandbox Code Playgroud)
假设一切正常,那么你只需:
struct push_lua_stack
{
// constructor taking reference to stack to push onto
// initialize count to 0, etc....
template <typename T>
void operator()(const T& pX)
{
// push pX onto lua stack
++count;
}
std::size_t count;
};
Run Code Online (Sandbox Code Playgroud)
最后:
std::size_t pushCount = iterate(someTuple, push_lua_stack()).count;
Run Code Online (Sandbox Code Playgroud)
如果这一切都有意义,请告诉我.
由于某些原因你似乎真的非常反对结构,只需创建一个这样的函数:
template <typename T>
void push_lua(const T& pX)
{
// push pX onto lua stack
}
Run Code Online (Sandbox Code Playgroud)
并改变一切专门调用该功能:
namespace detail
{
// just to keep things concise and readable
#define ENABLE_IF(x) std::enable_if<(x)>::type* = nullptr
// recursive case
template <std::size_t N, typename... Args>
typename ENABLE_IF(N >= 1) iterate(const std::tuple<Args...>& pTuple)
{
// specific function instead of generic function
push_lua(std::get<N - 1>(pTuple));
iterate<N - 1>(pTuple);
}
// base case
template <std::size_t N, typename... Args, typename Func>
typename ENABLE_IF(N == 0) iterate(const std::tuple<Args...>&, Func&)
{
// done
}
}
// iterate tuple
template <typename... Args>
void _push(const std::tuple<Args...>& pTuple)
{
detail::iterate<sizeof...(Args)>(pTuple);
}
Run Code Online (Sandbox Code Playgroud)
不知道你为什么要避免泛型功能,或者反对结构.
哦多态lambda会有多好.抛弃实用程序push_lua_stack类,然后写:
std::size_t count = 0;
iterate(someTuple, [&](auto pX)
{
// push onto lua stack
++count;
});
Run Code Online (Sandbox Code Playgroud)
那好吧.
| 归档时间: |
|
| 查看次数: |
2167 次 |
| 最近记录: |