c++ - 避免在字符串中进行 if-else 分支以进行类型调度

标签 c++ enums c++14 boost-preprocessor

通常,当您编写接受参数的 CLI 工具时,您必须处理它们。大多数时候,您希望根据参数的值在行为之间切换。

以下是一个常见的用例,其中程序接受一个类型,然后根据该类型打印一些内容。我正在使用 Boost 来预处理和自动生成整个 if-else 分支。 这在可维护性方面非常好,因为我只需要在引入新类型时更新 define。另一方面,它远非现代和优雅。

我考虑过使用 better-enums 来避免使用 if-else 使用 _from_string 将字符串转换为枚举实用功能。但是从枚举到类型的方法对我来说仍然是模糊的。

关于如何保持当前实现的良好可维护性但避免使用预处理器和宏功能的任何建议?

#include <iostream>
#include <cstdlib>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <type_traits>
using a_type = int;
using b_type = long;
using c_type = float;
using d_type = double;

#define TYPES (a)(b)(c)(d)

template<typename T>
void foo(){
    T num = 1;
    std::cout << typeid(decltype(num)).name() << " : "<< num << std::endl;
};

int main(int argc, char **argv)
{
if (argc < 1) {
    return 1;
}
std::string type = argv[1];

    if (false) {
#define LOOP_BODY(R, DATA, T)                  \
    }                                          \
    else if (type == BOOST_PP_STRINGIZE(T)) {  \
        foo<BOOST_PP_CAT(T, _type)>();         \

        BOOST_PP_SEQ_FOR_EACH(LOOP_BODY, _, TYPES);
#undef LOOP_BODY
    } else {
        std::cout << "ERROR: Unknown type " << type << std::endl;
    }

}

工作示例 https://wandbox.org/permlink/60bAwoqYxzU1EUdw

最佳答案

另一种方法是使用普通数组和 std::find_if 而不是 if-else:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <typeinfo>

struct Handler {
    char const* name;
    void(*fn)(std::string const&); // Or std::function<> to accept lambdas.
};

struct A {};
struct B {};

template<class T>
void foo(std::string const& name) {
    std::cout << "foo<" << typeid(T).name() << ">: " << name << '\n';
}

int main(int, char** av) {
    Handler const handlers[] = {
          {"a", foo<A>}
        , {"b", foo<B>}
    };
    std::string const name = av[1];
    auto handler = std::find_if(std::begin(handlers), std::end(handlers), [&name](auto const& h) {
        return name == h.name;
    });
    if(handler != std::end(handlers))
        handler->fn(name);
}

关于c++ - 避免在字符串中进行 if-else 分支以进行类型调度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48025783/

相关文章:

Java枚举反向查找

c++ - 是否可以在 Xcode 5.1 中使用 std::make_unique?

c++ - 为什么 vector<std::function> 的元素可以绑定(bind)到 C++ 中的不同函数签名?

java - OpenCSV - 注册自定义转换器

C++:将元组转换为类型 T

c++ - 为什么派生类不能在数组中工作? (C++)

c++ - 什么是悬空指针?

c++ - 错误: invalid conversion from 'int' to 'void*' [-fpermissive]

c++ - 函数模板的部分排序和非推导上下文在 MSVC 2017 中不起作用

c - Eclipse 符号无法解析