c++ - 中间的 C++ 可变参数模板更改元素
问题描述
我有用于添加、存储、跳转、返回和变量等指令的模板。然后我创建了 static_list 模板来存储这些指令。我想一一执行。我使用 SFINAE 并比较成员指令来检查当前指令的类型并相应地分支。这些是模板:
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;
};
//-------------static_list-------------
template<class ...Elements>
struct static_list {};
//-------------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;
};
//-------------variable_command_or_try_store-------------
template <bool condition, int index, typename list>
struct variable_command_or_try_store;
//-------------store_command_or_try_add-------------
template <bool condition, int index, typename list>
struct store_command_or_try_add;
//-------------execute_s-------------
template<int index, class ...Commands>
struct execute_s;
//-------------variable_command_or_try_store-------------
template <int index, typename ... Commands>
struct variable_command_or_try_store<false, index, static_list<Commands...>> {
static constexpr int value = store_command_or_try_add<static_list_get<index, static_list<Commands...>>::type::instruction == 2, index, static_list<Commands...>>::value;
};
template <int index, typename... Commands>
struct variable_command_or_try_store<true, index, static_list<Commands...>> {
static constexpr int value = execute_s<index + 1, static_list<Commands...>>::value;
};
//-------------store_command_or_try_add-------------
template <int index, typename ... Commands>
struct store_command_or_try_add<false, index, static_list<Commands...>> {
static constexpr int value = 0;
};
template <int index, typename... Commands>
struct store_command_or_try_add<true, index, static_list<Commands...>> {
static constexpr int value = execute_s<index + 1, NEW LIST WITH ONE CHANGED VALUE>::value;
};
//-------------execute_s-------------
template<int index, class ...Commands>
struct execute_s <index, static_list<Commands ...>> {
static constexpr int value = variable_command_or_try_store<static_list_get<index, static_list<Commands...>>::type::instruction == 1, index, static_list<Commands...>>::value;
};
template<class ...Commands>
constexpr int execute_v = execute_s<1, static_list<Commands...>>::value;
这是主要功能示例:
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");
}
我想反复循环浏览命令类型,如果类型合适,则执行命令并从列表中的下一个命令重新开始。目前我只实现了命令变量,它只是继续而不做任何事情,因为我已经从一开始就存储了它。接下来,如果它不是变量类型,我检查它是否是存储类型。如果不继续检查其他命令(尚未实现),则再次检查。如果是 store 命令,则继续执行 list 中的下一个命令,但 list 已更改,destinationVar 的值将通过 store 命令更改为 sourceVar 值。我怎样才能做到这一点?我使用 SFINAE 尝试过这样的事情,但它不起作用:
//-------------static_list_store-------------
template<size_t from, size_t to, class NewElements, class Element, class OldList>
struct static_list_store;
//-------------is_var_or_no_change-------------
template <bool Cond, size_t from, size_t to, class NewElements, class Element, class OldList>
struct is_var_or_no_change;
//-------------is_id_or_no_change-------------
template <bool Cond, size_t from, size_t to, class NewElements, class Element, class OldList>
struct is_id_or_no_change;
template<size_t from, size_t to, class NewElements, class Element, class ...OldElements>
struct is_var_or_no_change<false, from, to, NewElements, Element, static_list<OldElements...>> {
using type = static_list_store<from, to, static_list<NewElements, Element>, OldElements...>;
};
template<size_t from, size_t to, class NewElements, class Element, class ...OldElements>
struct is_var_or_no_change<true, from, to, NewElements, Element, static_list<OldElements...>> {
using type = is_id_or_no_change<Element::variableId == to, from, to, static_list<NewElements, Element>, OldElements...>;
};
//-------------is_id_or_no_change-------------
template<size_t from, size_t to, class NewElements, class Element, class ...OldElements>
struct is_id_or_no_change<false, from, to, NewElements, Element, static_list<OldElements...>> {
using type = static_list_store<from, to, static_list<NewElements, Element>, OldElements...>;
};
template<size_t from, size_t to, class NewElements, class Element, class ...OldElements>
struct is_id_or_no_change<true, from, to, NewElements, Element, static_list<OldElements...>> {
using type = static_list_store<from, to, static_list<NewElements, variable<Element::variableId, /*find var by id ::value for now 16*/16>>, OldElements...>;
};
//-------------static_list_store-------------
template<size_t from, size_t to, class NewElements, class Element, class ...OldElements>
struct static_list_store<from, to, NewElements, Element, static_list<OldElements...>> {
using type = is_var_or_no_change<Element::instruction == 1, from, to, static_list<NewElements, Element>, OldElements...>;
};
然后 store_command_or_try_add 将是:
template <int index, typename... Commands>
struct store_command_or_try_add<true, index, static_list<Commands...>> {
static constexpr int value = execute_s<index + 1, static_list_store<static_list_get<index, static_list<Commands...>>::type::sourceVariableId, static_list_get<index, static_list<Commands...>>::type::destinationVariableId, static_list<>, static_list<Commands...>>>::value;
};
解决方案
推荐阅读
- node.js - Node.JS 等待设置变量
- c - netcat 看不到 UDP 广播
- visual-studio - 当我悬停时,Razor/cshtml 调试变量不再显示值?
- .net - 无法在 Visual Studio 2012 中将 WSDL Web 引用添加到 .NET 项目
- javascript - HTML- 动态表的标题
- c# - 使用 BinaryFormatter 时不会保留对字段的更改 - 为什么?
- excel - 您如何根据 2 列进行排名?
- sparql - 如何使用 geosparql 计算两点之间的距离
- php - 如何清除php中的cookie
- c++ - 两个相同阵列元素之间的最短距离