C++0x:使用函数迭代元组

2024-05-20

我有一个名为_push它可以处理不同的参数,包括元组,并且应该返回推送元素的数量。

例如,_push(5)应该将“5”压入堆栈(lua栈 http://www.lua.org/manual/5.1/manual.html#lua_pushinteger)并返回 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;
}

假设你想推动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


我没有编译器来测试这些,所以你必须报告任何问题。

以下应该允许您迭代调用函数的元组。它基于您的逻辑,并进行了一些细微的更改。 (N is a std::size_t,这是第一个允许的参数Args (and 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;
}

假设一切正常,那么您将拥有:

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;
};

最后:

std::size_t pushCount = iterate(someTuple, push_lua_stack()).count;

让我知道这一切是否有意义。


由于出于某种原因,您似乎真的非常反对结构,因此只需创建一个如下所示的函数:

template <typename T>
void push_lua(const T& pX)
{
    // push pX onto lua stack
}

并更改所有内容以专门调用该函数:

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);
}

不知道为什么你会避免通用功能,或者如此反对结构。


哦,多态 lambda 会多好啊。放弃公用事业push_lua_stack类并只写:

std::size_t count = 0;

iterate(someTuple, [&](auto pX)
                    {
                        // push onto lua stack
                        ++count;
                    });

Oh well.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++0x:使用函数迭代元组 的相关文章

随机推荐