输出一个可能是三种类型之一的数字

Output a number that may be one of three types

我有一个变量x

它可以是 charuint8_tstd::string 类型。

我希望输出数字(不是字符),使用 涉及 std::cout 的相同表达式。这是因为我在生成的代码中使用了这个表达式。

在代码生成时,我目前不知道 xcharuint8_t 还是 std::string

如果 xchar 类型,

std::cout << x << std::endl 不起作用,因为它将输出字符而不是数字。

如果 xstd::string.

类型,

std::cout << +x << std::endl 不起作用 如果 x 的类型为 std::string

std::cout << (typeid(x) == typeid(uint8_t) || typeid(x) == typeid(char) ? +x : x) << std::endl 不起作用。

如果 xstd::string.

类型,

std::cout << (typeid(x) == typeid(uint8_t) || typeid(x) == typeid(char) ? static_cast<int>(x) : x) << std::endl 不起作用

我知道 std::cout 可以通过管道 std::hexstd::boolalpha 以多种方式配置,但我知道无法配置 std::cout 输出一个 char 作为一个数字,没有首先转换 char

有没有办法使用反射、运算符重载、模板或其他东西 这样就可以有一个统一的语句来输出 x 作为数字?

例如,如果 x 是 65,类型为 char,则所需的输出是 65,而不是 A

只需格式化一个帮助程序并专门化您想要适当自定义的版本。例如:

#include <iostream>

template <typename T>
struct formatter {
    T const& value;
};

template <typename T>
formatter<T> format(T const& value) {
    return formatter<T>{value};
}

template <typename T>
std::ostream& operator<< (std::ostream& out, formatter<T> const& v) {
    return out << v.value;
}

std::ostream& operator<< (std::ostream& out, formatter<char> const& v) {
    return out << int(v.value);
}

template <std::size_t N>
std::ostream& operator<< (std::ostream& out, formatter<char[N]> const& v) {
    return out << '\'' << v.value << '\'';
}


int main() {
    std::cout << "char=" << format('c') << " "
              << "int=" << format(17) << " "
              << "string=" << format("foo") << " "
              << "\n";
}

我猜您是在通用上下文中工作。所以你的基本问题是你需要static dispatch。三字母运算符 ? : 不提供此功能。它在 运行 时间进行评估,并且将始终调用相同的 operator<<.

所以你有两个选择:

  1. 使用部分专业化的助手 class

  2. 使用静态 if。即:

    if constexpr (std::is_integral<decltype(x)>::value)
      std::cout << static_cast<int>(x) << std::endl;
    else
      std::cout << x << std::endl;
    

后者需要 C++17。

这个解决方案对我有用。它通过使用 output 函数以及模板特化和 if constexpr:

将 char 输出为数字
#include <cstdint>
#include <iostream>
#include <string>

using namespace std::string_literals;

template <typename T> void output(std::ostream& out, T x)
{
    if constexpr (std::is_integral<decltype(x)>::value) {
        out << static_cast<int>(x);
    } else {
        out << x;
    }
}

int main()
{
    char x = 65;
    uint8_t y = 66;
    std::string z = "hi"s;

    // output: A
    std::cout << x << std::endl;

    // output: 65
    output(std::cout, x);
    std::cout << std::endl;

    // output: B
    std::cout << y << std::endl;

    // output: 66
    output(std::cout, y);
    std::cout << std::endl;

    // output: "hi"
    output(std::cout, z);
    std::cout << std::endl;

    return 0;
}

感谢 Dietmar Kühl 和 Marcel 提供的有用答案。