【问题标题】:How is it possible to generate an OR like statement compile time? C++如何生成类似 OR 的语句编译时间? C++
【发布时间】:2019-07-25 19:00:46
【问题描述】:

我这样定义了一个函数和一个类型枚举:

enum ActionType : int {
    ACTION_FOO, ACTION_BAR, ACTION_BAZ
};

template<int T>
bool TestAction(std::string input, Result& result);

TestAction 返回成功指示符,并将输出写入 Result 参数。它专门用于所有 ActionType 值。我这样称呼它:

std::string input = "test";
Result res;
bool ok = TestAction<ACTION_FOO>(input, res) || TestAction<ACTION_BAR>(input, res) || TestAction<ACTION_BAZ>(input, res);

只要一个调用返回一个真值,就不需要调用其他函数,所以|| 运算符在这里工作得很好。

代码按预期工作,但我想避免手动(或使用宏)编写 OR 语句,而是使用模板生成类似的代码编译时间。有没有可能?

如果我从错误的方向解决问题,我可以接受,但是请给我一些提示,告诉我如何重做这段代码。

【问题讨论】:

  • 你可以使用 tuple 的函数指针,但对我来说似乎不值得。
  • 函数指针元组完全没有必要
  • @J.AntonioPerez 我没有想到利用它总是调用同一个函数模板这一事实,因此您可以打包模板参数。

标签: c++ templates


【解决方案1】:

我会这样做:

#include <utility>

template <typename T, T ...I, typename F>
bool static_any_of(F &&func, std::integer_sequence<T, I...>)
{
    return (func(std::integral_constant<T, I>{}) || ...);
}

template <auto N, typename F>
bool static_any_of_n(F &&func)
{
    return static_any_of(std::forward<F>(func), std::make_integer_sequence<decltype(N),N>{});
}

enum ActionType : int
{
    ACTION_FOO, ACTION_BAR, ACTION_BAZ,
    ActionType_Count,
};

int main()
{
    bool ok = static_any_of_n<+ActionType_Count>([](auto index)
    {
        return TestAction<ActionType(index.value)>(/*...*/);
    });

    std::cout << ok;
}

【讨论】:

    【解决方案2】:

    我们可以通过编写可以接受多个操作的第二个版本的 TestAction 来做到这一点!

    // This is our base case 
    template<int T>
    bool TestAction(std::string input, Result& result);
    
    // This is the general case 
    template<int T, int T2, int... Ts>
    bool TestAction(std::string input, Result& result) {
        return TestAction<T>(input, result) || TestAction<T2, Ts...>(input, result); 
    }
    

    然后,要使用它,我们只需提供操作:

    std::string input = "test";
    Result res; 
    bool ok = TestAction<ACTION_FOO, ACTION_BAR, ACTION_BAZ>(input, res); 
    

    如果您使用的是 C++17,我们还可以使用折叠表达式消除递归:

    template<int... Ts>
    bool TestActions(std::string input, Result& result) {
        return (TestAction<Ts>(input, result) || ...);
    }
    

    其他建议:如果您不修改TestAction 中的任何位置的input,则可以通过将input 声明为const std::string&amp; 来消除复制,以便通过引用传递

    【讨论】:

    • 这样会复制input几次,不好。您可以通过使用折叠表达式来完全避免递归:删除typename T 并执行return (TestAction&lt;Ts&gt;(input, result) || ...);
    • 谢谢。我通过添加第二个参数来消除调用的歧义来修复它
    猜你喜欢
    • 2021-10-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2010-10-13
    • 2021-09-22
    • 1970-01-01
    • 2019-06-14
    • 2022-11-30
    相关资源
    最近更新 更多