1

我有一些我想用字符串表示的错误代码:

enum class ErrorCode
{
    OK,
    InvalidInput,
    BadAlloc,
    Other
};

我想创建一种直观且简单的方法来获取表示这些错误的字符串。简单的解决方案是:

std::string const ErrorCode2Str(ErrorCode errorCode)
{
  switch (errorCode)
  {
    case OK:
    return "OK";
    case InvalidInput:
    return "Invalid Input";
    case BadAlloc:
    return "Allocation Error";
    case Other:
    return "Other Error";
    default:
    throw Something;
  }
}

有没有更好的办法?我可以ErrorCode以某种方式重载字符串转换吗?我可以创建一个ErrorCode::str()函数吗?这个问题有标准解决方案吗?

4

3 回答 3

6

一种可能性是地图:

class to_str { 
    std::unordered_map<ErrorCode, std::string> strings;
public:
    to_str() {
        strings[ErrorCode::OK] = "Ok";
        strings[ErrorCode::InvalidInput] = "Invalid Input";
        strings[ErrorCode::BadAlloc] = "Allocation Error";
        strings[ErrorCode::Other] = "Other";
    }

    std::string operator()(ErrorCode e) { 
        return strings[e];
    }
};

// ...
auto e = foo(some_input);
if (e != ErrorCode::OK)
   std::cerr << to_str()(e);

这显然不是一个巨大的差异,但我发现它至少更具可读性,并且认为从长远来看它可能更易于维护。

于 2013-10-17T04:04:10.537 回答
3

没有完美的解决方案,很多图书馆都在做你目前正在做的事情。

但是如果你想要一种不同的方式,你可以把错误变成这样的类:

#include <iostream>
#include <string>
class Error
{
public:
    Error(int key, std::string message) : key(key), message(message){}
    int key;
    std::string message;
    operator int(){return key;}
    operator std::string(){ return message; }
    bool operator==(Error rValue){return this->key == rValue.key; } 
};

int main()
{
    Error e(0, "OK");

    int errorCode = e;
    std::string errorMessage = e;

    std::cout << errorCode << " " << errorMessage;
}
于 2013-10-17T04:05:32.743 回答
1

尽管存在许多简单的方法来进行枚举到字符串或字符串到枚举的转换,但我想在这里考虑一种更通用的方法。

为什么 C++ 不允许本机构造呢?主要有两个原因:

第一个是技术性的:C++ 没有任何反射机制:简单的编译符号不复存在(变成了数字)。而且由于它们不存在,因此您无法将它们取回。

第二个更多是编程问题:枚举在编译器和程序员之间“共享”。字符串文字在程序和最终用户之间共享。那可能不是程序员,也可能不会说英语(而且我们不知道他说什么)。

解决问题的一般方法是将其分成两部分:一个在流级别,另一个在本地化级别。

当你写作时会发生什么std::cout << 42

实现,operator<<(ostream&, int)实际上调用use_facet<num_put<char> >(cout.getloc()).do_put(int)最终使用numpunct定义如何处理符号、小数分隔符和数字组分隔符的方面。

处理枚举输出的标准方法是,通过实现一个ostrea<<enumeral运算符,该运算符获取一个构面并在其上调用一个方法来实际写入该字符串。

这样的方面可以实现多次,并且可用于每种支持的语言。

这并不容易和直接,但这就是 C++ I/O 的构思方式。

一旦你完成了所有这些,获取字符串的惯用方法是使用一个 strngstream,它带有一个支持所有枚举和类所需的方面的本地。

太复杂了?或许。但是如果你觉得这太复杂了,那就停下来教std::cout << "Hello wrld" << std::endl;写一个更简单的“输出库”。

于 2013-10-17T07:11:28.873 回答