首页 > 解决方案 > C++ 模板发送“错误参数”是一种不好的做法?

问题描述

std::stoi 在特定情况下会引发一些错误。我不想使用 try/catch 块,所以我在 google 上搜索了一些关于 char 转换的信息,发现这std::from_chars正是我想要的,没有那些 try/catch 块。

显然,std::from_chars直接使用效果很好,但我不喜欢这种语法。所以我开始编写自己的ToInt(),ToFloat()等。然后就像:“好吧,这听起来很愚蠢,让我们使用模板吧”。

我在这里 :

#include <string>
#include <charconv>
#include <iostream>

template <typename T>
T ToNumber(const char* str, T varType)
{
    if (!str)
        return 0;
    T var = 0;
    std::from_chars(str, str + strlen(str), var);
    return var;
}

int main()
{
    std::string t = "123.5";

    auto a = ToNumber(t.c_str(), (int)0); // a will be an int (123)
    float b = ToNumber(t.c_str(), (int)0); // b will store the value as int (123)
    auto c = ToNumber(t.c_str(), (float)0); // c will be a float (123.5)

    std::cout << a;
    return 0;
}

它确实有效,这不是问题。但我想知道......发送“错误参数”(T varType)以完成演员表并启用是一种好习惯auto吗?

如果不是,那么编写这样一个函数的聪明方法是什么?

提前致谢

标签: c++templates

解决方案


您没有检查std::from_chars失败的返回值,例如:

auto [p, ec] = std::from_chars(str, str + strlen(str), var);
if (ec != std::errc()) {
    ...
}

也就是说,在T不使用类型转换的输入参数的情况下处理模板参数的另一种方法是简单地在调用站点显式指定所需的类型,例如:

template <typename T>
T ToNumber(const char* str)
{
    if (!str)
        return T{};
    T var{};
    auto [p, ec] = std::from_chars(str, str + strlen(str), var);
    if (ec != std::errc())
        return T{};
    return var;
}

auto a = ToNumber<int>(t.c_str());
float b = ToNumber<int>(t.c_str());
auto c = ToNumber<float>(t.c_str());

否则,您可以通过引用输出参数使用模板参数推导(就像这样std::from_chars()做一样),例如:

template <typename T>
bool ToNumber(const char* str, T &var)
{
    if (!str)
        return false;
    auto [p, ec] = std::from_chars(str, str + strlen(str), var);
    return (ec == std::errc());
}

int a;
ToNumber(t.c_str(), a);

int tmp;
ToNumber(t.c_str(), tmp);
float b = tmp;

float c;
ToNumber(t.c_str(), c);

推荐阅读