首页 > 解决方案 > 将模板类型限制为枚举类

问题描述

下面的函数get_from_string基本上string通过创建 astringstream并将其string写入变量(的指针)来将 a 转换为变量。之后,它返回是否成功。如果变量是 a enum class,它会绕过enum class'underlying_type并使用 astatic_cast来达到相同的效果。

下面的代码完美运行,但我无法摆脱这两个get_from_string_helper_structs。我可以在没有任何辅助结构且仅使用函数的情况下解决此问题吗?

#include <iostream>
#include <sstream>

template <typename T, typename U = std::underlying_type_t<T>>
U to_underlying(T v) {
  return static_cast<U>(v);
}

template <typename T, typename U = std::underlying_type_t<T>>
bool get_enum_from_string(T *target, const std::string &input) {
  U n;
  bool valid_input = static_cast<bool>(std::istringstream(input) >> n);
  *target = static_cast<T>(n);
  return valid_input;
}

template <typename T>
bool get_non_enum_from_string(T *target, const std::string &input) {
  T n;
  bool valid_input = static_cast<bool>(std::istringstream(input) >> n);
  *target = n;
  return valid_input;
}

template <typename T, class Enable = void>
struct get_from_string_helper_struct {
  bool get(T *target, const std::string &input) {
    return get_non_enum_from_string(target, input);
  }
};

template <typename T>
struct get_from_string_helper_struct<
    T, typename std::enable_if<std::is_enum<T>::value>::type> {
  bool get(T *target, const std::string &input) {
    return get_enum_from_string(target, input);
  }
};

template <typename T>
bool get_from_string(T *target, const std::string &input) {
  return get_from_string_helper_struct<T>().get(target, input);
}

enum class foo : uint8_t {
  foo1 = 1,
  foo2 = 2
};

int main(int argc, char const *argv[]) {
  bool valid = false;

  foo bar1;
  valid = get_from_string(&bar1, "1");
  std::cout << to_underlying(bar1) << (valid ? " True" : " False") << std::endl;

  uint8_t bar2;
  valid = get_from_string(&bar2, "1");
  std::cout << bar2 << (valid ? " True" : " False") << std::endl;

  return 0;
}

输出:

1 True
1 True

标签: c++templatesenums

解决方案


使用 C++17,您可以这样做:

template <typename T>
bool get_from_string(T *target, const std::string &input) {
    if constexpr (std::is_enum_v<T>) {
        std::underlying_type_t<T> value{};
        auto res = get_from_string(&value, input);
        *target = static_cast<T>(value);
        return res;
    } else {
        return static_cast<bool>(std::istringstream(input) >> *target);
    }
}

演示


推荐阅读