首页 > 解决方案 > Extending std::to_string to support enums and pointers

问题描述

I have the following template function ToString that uses std::to_string for arithmetic types and tries doing a static_cast for pointer and enum types.

#include <iostream>
#include <string>

template <typename T>
std::string ToString(T val)
{
    if (std::is_arithmetic<T>::value)
    {
        return std::to_string(val);
    }

    if (std::is_enum<T>::value || std::is_pointer<T>::value)
    {
        return std::to_string(static_cast<size_t>(val));
    }
}

enum class MyEnum : int
{
    E1,
    E2
};

int main(int argc, char* argv[])
{
    MyEnum e = MyEnum::E1;
    const void* ptr = &e;

    std::cout << ToString(e) << std::endl;
    std::cout << ToString(ptr) << std::endl;
}

The code above doesn't compile. Is there a way I can achieve the desired functionality?

The compilation errors on VS2017 are

Error   C2440   'static_cast': cannot convert from 'T' to 'size_t'
Error   C2665   'std::to_string': none of the 9 overloads could convert all the argument types

标签: c++

解决方案


你需要使用if constexpr. 否则,您std::to_string使用无法编译的指针或枚举实例化 (C2665)。

此外,您不能将指针静态转换为整数 (C2440)。你需要重新解释演员表。

此外,如果传递的参数既不是枚举、指针也不是算术类型,您的函数也没有返回值。在这种情况下,行为是未定义的。解决方案:总是返回一些东西(如果模板参数无效,则编译失败)。

此外,size_t不保证足够大以表示所有指针值。你想要std::uintptr_t

而且您可能希望使用std::underlying_type_t来获取正确的类型enum class

if constexpr (std::is_pointer<T>::value) {
    return std::to_string(reinterpret_cast<std::uintptr_t>(val));
} else if constexpr (std::is_enum<T>::value)
{
    return std::to_string(static_cast<std::underlying_type_t<T>>(val));
} else {
    return std::to_string(val);
}

添加缺少的标题后,这应该可以工作。

PS 设计说明:现在打印指针、整数或枚举在输出中都是相同的。您可能想要添加一些前缀或类似的东西来消除结果的歧义。


推荐阅读