c++ - 参数包的递归迭代

标签 c++ templates visual-studio-2015 c++14 variadic-templates

我目前正在尝试实现一个函数,它接受一些data 和一个参数包...args。我在内部调用了另一个函数,它递归地迭代给定的参数。

遗憾的是我在编译它时遇到了一些问题。显然,编译器一直在尝试编译递归函数,而不是停止递归的重载。

有人知道问题出在哪里吗?

class Sample
{
public:
    template<class ...TArgs, std::size_t TotalSize = sizeof...(TArgs)>
    static bool ParseCompositeFieldsXXX(const std::vector<std::string> &data, TArgs &&...args)
    {
        auto field = std::get<0>(std::forward_as_tuple(std::forward<TArgs>(args)...));

        //bool ok = ParseField(field, 0, data);
        auto x = data[0];
        bool ok = true;

        if (TotalSize > 1)
            return ok && ParseCompositeFields<1>(data, std::forward<TArgs>(args)...);
        return ok;
    }

private:
    template<std::size_t Index, class ...TArgs, std::size_t TotalSize = sizeof...(TArgs)>
    static bool ParseCompositeFields(const std::vector<std::string> &data, TArgs &&...args)
    {
        auto field = std::get<Index>(std::forward_as_tuple(std::forward<TArgs>(args)...));

        //bool ok = ParseField(field, Index, data);
        auto x = data[Index];
        bool ok = true;

        if (Index < TotalSize)
            return ok && ParseCompositeFields<Index + 1>(data, std::forward<TArgs>(args)...);
        return ok;
    }

    template<std::size_t Index>
    static bool ParseCompositeFields(const std::vector<std::string> &data)
    {
        volatile int a = 1 * 2 + 3;
    }
};

int wmain(int, wchar_t**)
{
    short       x1 = 0;
    std::string x2;
    long long   x3 = 0;

    Sample::ParseCompositeFieldsXXX({ "1", "Sxx", "-5,32" }, x1, x2, x3);

    return 0;
}

\utility(446): error C2338: tuple index out of bounds
...
\main.cpp(56): note: see reference to class template instantiation 'std::tuple_element<3,std::tuple>' being compiled

最佳答案

替代方法

您似乎在这里使用了相当古老的技术。 Simple expansion是您要搜索的内容:

#include <cstddef>
#include <utility>
#include <tuple>
#include <vector>
#include <string>

class Sample
{
    template <std::size_t index, typename T>
    static bool parse_field(T&& field, const std::vector<std::string>& data)
    {
        return true;
    }

    template <typename Tuple, std::size_t ... sequence>
    static bool parse_impl(Tuple&& tup, const std::vector<std::string>& data, std::index_sequence<sequence...>)
    {
        using expander = bool[];
        expander expansion{parse_field<sequence>(std::get<sequence>(tup), data)...};

        bool result = true;
        for (auto iter = std::begin(expansion); iter != std::end(expansion); ++iter)
        {
            result = result && *iter;
        }

        return result;
    }

public:
    template<class ...TArgs, std::size_t TotalSize = sizeof...(TArgs)>
    static bool ParseCompositeFieldsXXX(const std::vector<std::string> &data, TArgs &&...args)
    {

        return parse_impl(std::forward_as_tuple(std::forward<TArgs>(args)...),
                          data, std::make_index_sequence<sizeof...(TArgs)>{});
    }


};

int main()
{
    short       x1 = 0;
    std::string x2;
    long long   x3 = 0;

    Sample::ParseCompositeFieldsXXX({ "1", "Sxx", "-5,32" }, x1, x2, x3);

    return 0;
}

如果您正在查看类似数组的内容,那么它就是数组。除非需要,否则不要使用递归,因为它通常会使事情变得复杂。当然也有异常(exception)。

让它变得更好

如您所见,这里甚至不需要上课。只需将其删除即可。

可能遇到的问题

如果调用顺序很重要,可能会出现一个问题。 IIRC,在 C++17 之前,它没有很强的求值顺序,所以有时你可能会失败。

关于c++ - 参数包的递归迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47790737/

相关文章:

c++ - OpenGL glMatrixMode 帮助

typescript - 带有 Minification/Uglify 的 Angular2 TypeScript 转译器

c++ - Visual Studio unordered_set 异常,适用于 Codeblocks

C++ 枚举类作为可变模板参数

html - 组合上下文和表单时,模板显示标记而不是页面

angular - node_modules - 未找到 Zipproto.ts 和 mergeproto.ts 文件

C++ 程序意外终止

c++ - 为什么编译器优化会破坏我的代码?

c++ - 从文本文件中读取行并存储在 C++ 中的字符数组中

c++ - 为 EventDriver 传递和存储模板函数指针