【问题标题】:Is it possible to union variable conversion function?是否可以联合变量转换功能?
【发布时间】:2022-08-09 14:18:48
【问题描述】:

例如,有三个变量转换函数。

//Int
int toInt(std::string input)
{
    int ret = strtol(input.c_str(), 0, 10);
    return ret;
}

//Double
double toDouble(std::string input)
{
    double ret = strtod(input.c_str(), 0);
    return ret;
}

//Const char*
const char* toChar(std::string input)
{
    return input.c_str();
}

我想组合这些功能,如下所示:

~~ toConvert(std::string input)
{
    if ( Variable type is Int )
        return strtol(~~~)
    else if ( Varibale type is Double )
        return strtod(~~~)
    ...
// Using
int    i = toConvert<int>(input);
double d = toConvert<double>(input);
const char* c = toConvert<const char*>(input);

可能吗?

请帮助实现上述功能。

    标签: c++ templates


    【解决方案1】:

    您的“使用”代码将模板参数传递给toConvert(),因此请确保toConvert() 实际上是一个模板,然后您可以专攻它适用于您想要的每种类型,例如:

    template<typename T>
    T toConvert(std::string &input) { return T{}; /* or, throw an exception... */ }
    
    template<>
    int toConvert<int>(std::string &input)
    {
        return strtol(input.c_str(), 0, 10);
    }
    
    template<>
    double toConvert<double>(std::string &input)
    {
        return strtod(input.c_str(), 0);
    }
    
    template<>
    const char* toConvert<const char*>(std::string &input)
    {
        return input.c_str();
    }
    

    或者,如果您使用 C++17 或更高版本,则可以在单个模板中使用 if constexpr

    #include <type_traits>
    
    template<typename T>
    T toConvert(std::string &input)
    {
        if constexpr (std::is_same_v<T, int>)
            return strtol(input.c_str(), 0, 10);
        else if constexpr (std::is_same_v<T, double>)
            return strtod(input.c_str(), 0);
        else if constexpr (std::is_same_v<T, const char*>)
            return input.c_str();
        else
            return T{}; // or, throw an exception, or static_assert a compiler error...
    }
    

    请注意,无论哪种情况,我都将输入参数更改为std::string&amp;。您的原始代码按值采用 std::string,这意味着它采用复制调用者的字符串,因此当复制的std::stringreturn 上被释放时,const char* 转换将返回一个指向无效内存的悬空指针。相反,通过引用,您可以避免该副本。

    您可能很想改用 const std::string&amp; 引用,但这将允许像 toConvert&lt;const char*&gt;("string") 这样的调用编译但仍返回一个悬空指针,因为编译器必须创建一个临时的 std::string 来绑定到 const 引用.但是字符串文字不能绑定到非常量引用。

    【讨论】:

      【解决方案2】:

      这可以使用 C++17 的 if constexpr 语法来实现。例如:

      template <typename T>
      constexpr bool dependent_false = false;
      
      template <typename T>
      T convertTo(const std::string& input)
      {
          if constexpr (std::is_same_v<T, int>) {
              return std::stoi(input);
          } else if constexpr (std::is_same_v<T, double>) {
              return std::stod(input);
          } else {
              static_assert(dependent_false<T>, "Can't convert to the specified type");
          }
      }
      

      Live Demo

      整个dependent_false 的存在是为了使static_assertion 依赖于模板参数,以便仅在实例化函数模板时才对其进行检查。只是 C++ 模板规则的一个奇怪的怪癖。


      请注意,我留下了 const char* 案例。它与其他语义非常不同,因为c_str 返回的指针指向std::string 对象拥有的内存。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-16
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 2016-02-22
      相关资源
      最近更新 更多