[英]C++ template recursion undefined type
I have templates for instructions like add, store, jump, return and variable.我有用于添加、存储、跳转、返回和变量等指令的模板。 Then I created static_list template for storing these instructions.
然后我创建了 static_list 模板来存储这些指令。 I want to execute them one by one.
我想一一执行。 I use enable_if_else and comparing member instruction for checking what type the current instruction is and branch accordingly.
我使用 enable_if_else 并比较成员指令来检查当前指令的类型并相应地分支。 However, I cant continue after the first check, if it is a variable type instruction.
但是,如果它是变量类型指令,我在第一次检查后无法继续。 The execute_v and execute_s are working when it is like this:
当它是这样的时候,execute_v 和 execute_s 正在工作:
template<int index, class ...Commands>
struct execute_s <index, static_list<Commands ...>> {
static constexpr int value = enable_if_else_v < static_list_get<index, static_list<Commands...>>::type::instruction == 1,
1,
0>::result ;
};
It returns 1 or 0 depending on what type of instruction I put as first into execute_v.它返回 1 或 0,具体取决于我首先放入 execute_v 的指令类型。 This works correctly.
这可以正常工作。 However when I want to recursively continue onto next command, it wont work, it looks like this:
但是,当我想递归地继续执行下一个命令时,它不起作用,它看起来像这样:
template<int index, class ...Commands>
struct execute_s <index, static_list<Commands ...>> {
static constexpr int value = enable_if_else_v < static_list_get<index, static_list<Commands...>>::type::instruction == 1,
execute_s<index + 1, Commands...>::value,
0>::result ;
};
The problem is with execute_s<index + 1, Commands...>::value
as it seems it does not stop when instruction is not variable type, but I dont know why is it so, because it should stop then.问题在于
execute_s<index + 1, Commands...>::value
因为当指令不是变量类型时它似乎不会停止,但我不知道为什么会这样,因为它应该停止。 Maybe I am wrongly unpacking Commands?也许我错误地解压命令? How can I achieve that I can push forward next index with all the commands to the next level of recursion?
我怎样才能实现我可以将所有命令的下一个索引推进到下一个递归级别? These are the templates:
这些是模板:
template<size_t VariableId, int InitValue>
struct variable {
static constexpr size_t variableId = VariableId;
static constexpr int value = InitValue;
static constexpr int instruction = 1;
};
template<size_t DestinationVariableId, size_t SourceVariableId>
struct store {
static constexpr size_t destinationVariableId = DestinationVariableId;
static constexpr size_t sourceVariableId = SourceVariableId;
static constexpr int instruction = 2;
};
template<size_t DestinationVariableId, size_t SourceVariableId>
struct add {
static constexpr size_t destinationVariableId = DestinationVariableId;
static constexpr size_t sourceVariableId = SourceVariableId;
static constexpr int instruction = 3;
};
template<size_t VariableId, size_t CommandNumber>
struct jump_if_not_zero {
static constexpr size_t variableId = VariableId;
static constexpr size_t commandNumber = CommandNumber;
static constexpr int instruction = 4;
};
template<size_t VariableId>
struct ret {
static constexpr size_t variableId = VariableId;
static constexpr int instruction = 5;
};
//-------------enable_if_else_v-------------
template<bool Cond, int TrueValue, int FalseValue>
struct enable_if_else_v;
template<int TrueValue, int FalseValue>
struct enable_if_else_v<true, TrueValue, FalseValue> {
static constexpr int result = TrueValue;
};
template<int TrueValue, int FalseValue>
struct enable_if_else_v<false, TrueValue, FalseValue> {
static constexpr int result = FalseValue;
};
//-------------static_list_get-------------
template<size_t Idx, class List>
struct static_list_get;
template<size_t Idx, class FirstElement, class ...Elements>
struct static_list_get<Idx, static_list<FirstElement, Elements ...>>
: static_list_get<Idx - 1, static_list<Elements ...>> {
};
template<class FirstElement, class ...Elements>
struct static_list_get<1, static_list<FirstElement, Elements ...>> {
using type = FirstElement;
};
//-------------execute_s-------------
template<int index, class ...Commands>
struct execute_s;
template<int index, class ...Commands>
struct execute_s <index, static_list<Commands ...>> {
static constexpr int value = enable_if_else_v < static_list_get<index, static_list<Commands...>>::type::instruction == 1,
execute_s<index + 1, Commands...>::value,
0>::result ;
};
template<class ...Commands>
constexpr int execute_v = execute_s<1, static_list<Commands...>>::value;
And this is main function example:这是主要的 function 示例:
int main() {
constexpr size_t PREV = 0;
constexpr size_t CURR = 1;
constexpr size_t OLD_CURR = 2;
constexpr size_t N = 3;
constexpr size_t MINUS1 = 4;
constexpr int fib_n = execute_v<
variable<PREV, 0>, // 1: PREV = 0
variable<CURR, 1>, // 2: CURR = 1
variable<OLD_CURR, 0>, // 3: OLD_CURR = 0
variable<N, 10>, // 4: N = 10
variable<MINUS1, -1>, // 5: MINUS1 = -1
jump_if_not_zero<N, 8>, // 6: if (N > 0) goto 8
ret<PREV>, // 7: return 0
store<OLD_CURR, CURR>, // 8: OLD_CURR = CURR
add<CURR, PREV>, // 9: CURR += PREV
store<PREV, OLD_CURR>, // 10: PREV = OLD_CURR
add<N, MINUS1>, // 11: N += -1
jump_if_not_zero<N, 8>, // 12: if (N > 0) goto 8
ret<PREV> // 13: return PREV
>;
static_assert(fib_n == 55, "Wrong result");
}
Compile errors: use of undefined type 'execute_s<2, variable<0, 0>, variable<1, 1>, variable<2, 0>...(all commands)..., ret<0>>'编译错误:使用未定义类型 'execute_s<2, variable<0, 0>, variable<1, 1>, variable<2, 0>...(all commands)..., ret<0>>'
I tried to pack Commands to list like this: execute_s<index + 1, static_list<Commands...>>::value
, but it was not working, it does not stop the recursion.我试图将命令打包成这样的列表:
execute_s<index + 1, static_list<Commands...>>::value
,但它不起作用,它不会停止递归。
Your example is a bit incomplete, but I'll try to give you the general idea with SFINAE.您的示例有点不完整,但我会尝试为您提供 SFINAE 的总体思路。
template <bool condition, int index, typename list>
struct get_next_command_or_zero;
template <int index, typename list>
struct get_next_command_or_zero<false, index, list> {
static constexpr int value = 0;
}
template <int index, typename... Commands>
struct get_next_command_or_zero<true, index, static_list<Commands...>> {
static constexpr int value = execute_s<index + 1, Commands...>::value; // I think you example is wrong here since, execure_s is expecting a static_list?
}
Here we use sfinae to pick the right partial specialization first, so the lookup of execure_s<...>::value
is only done when that path is chosen and otherwise discarded and left unevaluated.在这里,我们首先使用 sfinae 来选择正确的偏特化,因此
execure_s<...>::value
的查找仅在选择了该路径时才进行,否则将被丢弃且未求值。
Now in execute_s
you can use this like现在在
execute_s
你可以这样使用
static constexpr int value = get_next_command_or_zero<static_list_get<index, static_list<Commands...>>::type::instruction == 1, index, static_list<Commands...>>::value;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.