我目前正在尝试实现一个函数,该函数接受一些string str = string.Join("Insert into " + tname+ "(id, t, v) values(" + lc+ ", " + mc+ ", " + rc+ ");", Environment.NewLine);
File.AppendAllText(fileName, str);
和一个参数包data
。在里面我调用另一个函数,递归迭代给定的参数。
可悲的是,我有一些问题要编译它。显然编译器一直在尝试编译递归函数,但不会重载以停止递归。
有谁知道问题是什么?
...args
\ utility(446):错误C2338:元组索引超出范围
...
\ main.cpp(56):注意:请参阅类模板的引用 实例化'std :: tuple_element< 3,std :: tuple>'正在编制
答案 0 :(得分:2)
有谁知道问题是什么?
关键点在于:
if (Index < TotalSize)
return ok && ParseCompositeFields<Index + 1>(data, std::forward<TArgs>(args)...);
首先,要使逻辑正确,条件应为Index < TotalSize - 1
。,因为元组元素计数从零开始。
此外,即使Index == TotalSize - 1
,编译器仍然被强制实例化ParseCompositeFields<Index + 1>
(因为它必须编译if分支),实际上是ParseCompositeFields<TotalSize>
。但这会导致您在尝试实例化std::get<TotalSize>
时出现错误。
因此,为了仅在条件满足时有条件地编译if分支, 必须使用if constexpr(Index < TotalSize - 1)
(参见godbolt)。对于C ++ 14,您必须使用模板特化和函数对象:
class Sample
{
template<std::size_t Index, bool>
struct Helper {
template<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;
return ok && Helper<Index + 1, (Index < TotalSize - 1)>::ParseCompositeFields(data, std::forward<TArgs>(args)...);
}
};
template<std::size_t Index>
struct Helper<Index, false> {
template<class ...TArgs, std::size_t TotalSize = sizeof...(TArgs)>
static bool ParseCompositeFields(const std::vector<std::string> &data, TArgs &&...args) {
volatile int a = 1 * 2 + 3;
return true;
}
};
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;
return ok && Helper<1, (TotalSize > 1)>::ParseCompositeFields(data, std::forward<TArgs>(args)...);
}
};
答案 1 :(得分:2)
你似乎在这里使用相当古老的技术。 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;
}
如果您正在查看类似数组的内容,那么它就是数组。除非需要,否则不要使用递归,因为它通常会使其变得复杂。当然也有例外。
如你所见,人们甚至不需要这里的课程。只需删除它。
如果调用顺序很重要,可能会出现一个问题。 IIRC,在C ++ 17之前,它没有强大的评估顺序,因此有时可能会失败。