简短版本:无论如何在enum
类中嵌套函数,以及EnumClass::EnumLabel
您可以使用EnumClass::to_string(EnumClass value)
等有用的相关函数具有全局函数EnumClass_to_string(EnumClass value)
。
长版本:所以我正在玩OpenGL,它带有一堆整数#defines
,用于GPU上的各种功能。对于C兼容性,这些定义在其标签之外没有真正的结构,这使得使用不正确的定义变得容易。为了帮助补救这个新手bug的来源,我一直在将相关的定义分组到enum
类,如下面的调试消息源示例:
enum class Source {
API = GL_DEBUG_SOURCE_API,
WINDOW_SYSTEM = GL_DEBUG_SOURCE_WINDOW_SYSTEM,
SHADER_COMPILER = GL_DEBUG_SOURCE_SHADER_COMPILER,
THIRD_PARTY = GL_DEBUG_SOURCE_THIRD_PARTY,
APPLICATION = GL_DEBUG_SOURCE_APPLICATION,
OTHER = GL_DEBUG_SOURCE_OTHER
};
由于这些通常用于调试输出,我决定使用to_string
函数来简化将其含义输出到日志文件。
std::string source_to_string(KHR_debug::Source source) {
if(source == KHR_debug::Source::API) {
return "GL_DEBUG_SOURCE_API";
} else if(source == KHR_debug::Source::WINDOW_SYSTEM) {
return "GL_DEBUG_SOURCE_WINDOW_SYSTEM";
} else if(source == KHR_debug::Source::SHADER_COMPILER) {
return "GL_DEBUG_SOURCE_SHADER_COMPILER";
} else if(source == KHR_debug::Source::THIRD_PARTY) {
return "GL_DEBUG_SOURCE_THIRD_PARTY";
} else if(source == KHR_debug::Source::APPLICATION) {
return "GL_DEBUG_SOURCE_APPLICATION";
} else if(source == KHR_debug::Source::OTHER) {
return "GL_DEBUG_SOURCE_OTHER";
} else {
return "INVALID_SOURCE_ENUM";
}
}
但是,我认为如果我可以在enum
类本身内嵌套该辅助函数,那将更加简洁。因此,您可以使用source_to_string(source)
而不是调用Source::to_string(source)
。我很欣赏这个功能,如果您使用旧式enum
类,只需将enum
包装在类/结构中,但是我使用C ++ 11的原因之一{{1类是因为它们增加了类型安全性。
我尝试在enum
类旁边有一个类/命名空间,但这似乎覆盖了一个现有的定义。
答案 0 :(得分:10)
这里惯用的事情是使用免费功能:就像你想做的那样
using std::to_string;
int ltuae = 42;
std::cout << "The answer: " << to_string(ltuae) << std::endl;
你可以做到
KHR_debug::Source s /* = ... */;
std::cout << "The source: " << to_string(s) << std::endl;
注意 如上所述,它采用了C ++的“隐藏”功能:Argument Dependent Lookup。编写
to_string
将找到KHR_debug::to_string
,因为该命名空间包含参数类型。
#include <iostream>
#include <string>
namespace KHR_debug
{
enum class Source {
API /*= GL_DEBUG_SOURCE_API */,
WINDOW_SYSTEM /*= GL_DEBUG_SOURCE_WINDOW_SYSTEM */,
SHADER_COMPILER /*= GL_DEBUG_SOURCE_SHADER_COMPILER*/,
THIRD_PARTY /*= GL_DEBUG_SOURCE_THIRD_PARTY */,
APPLICATION /*= GL_DEBUG_SOURCE_APPLICATION */,
OTHER /*= GL_DEBUG_SOURCE_OTHER */
};
std::string to_string(Source source) {
switch(source) {
case Source::API: return "GL_DEBUG_SOURCE_API";
case Source::WINDOW_SYSTEM: return "GL_DEBUG_SOURCE_WINDOW_SYSTEM";
case Source::SHADER_COMPILER: return "GL_DEBUG_SOURCE_SHADER_COMPILER";
case Source::THIRD_PARTY: return "GL_DEBUG_SOURCE_THIRD_PARTY";
case Source::APPLICATION: return "GL_DEBUG_SOURCE_APPLICATION";
case Source::OTHER: return "GL_DEBUG_SOURCE_OTHER";
default: return "INVALID_SOURCE_ENUM";
}
}
}
int main()
{
using std::to_string;
int ltuae = 42;
std::cout << "The answer: " << to_string(ltuae) << std::endl;
KHR_debug::Source s = KHR_debug::Source::APPLICATION;
std::cout << "The source: " << to_string(s) << std::endl;
}
请注意我是如何巧妙地更改您的to_string
方法以使用switch
所在的位置:)
答案 1 :(得分:2)
这是不可能直接的。
enum
只能声明:access enum class enumeration-identifier [:underlying-type] { enumerator-list } [var];
。它们只能包含枚举列表。
但也许你可以使用包装器struct
:
#include <string>
#include <iostream>
struct SourceWrapper
{
enum Source {
API = 0,
WINDOW_SYSTEM = 1,
SHADER_COMPILER = 2,
THIRD_PARTY = 3,
APPLICATION = 4,
OTHER = 5,
};
static std::string ToString( Source source ) {
if(source == Source::API) {
return "GL_DEBUG_SOURCE_API";
} else if(source == Source::WINDOW_SYSTEM) {
return "GL_DEBUG_SOURCE_WINDOW_SYSTEM";
} else if(source == Source::SHADER_COMPILER) {
return "GL_DEBUG_SOURCE_SHADER_COMPILER";
} else if(source == Source::THIRD_PARTY) {
return "GL_DEBUG_SOURCE_THIRD_PARTY";
} else if(source == Source::APPLICATION) {
return "GL_DEBUG_SOURCE_APPLICATION";
} else if(source == Source::OTHER) {
return "GL_DEBUG_SOURCE_OTHER";
} else {
return "INVALID_SOURCE_ENUM";
}
}
};
PS:为了测试目的,我删除了你的GL宏。
答案 2 :(得分:1)
您的另一个选择是完全废弃enum
并使用稍微复杂的类型。这在语法上稍微不那么友好,但是它允许你在enum
“实例”(实际上是静态常量)上放置方法。
// Source.h
#include <string>
class Source
{
private:
const int value;
const std::string name;
Source(const int value, const std::string name)
: value(value), name(name) { }
public:
inline std::string ToString() const { return this->name; }
inline bool operator==(const Source &that) const
{
return this->value == that.value;
}
inline bool operator!=(const Source &that) const
{
return !(*this == that);
}
static const Source Api;
static const Source WindowSystem;
static const Source ShaderCompiler;
static const Source ThirdParty;
static const Source Application;
static const Source Other;
};
和
// Source.cpp
const Source Source::Api = Source(0, "GL_DEBUG_SOURCE_API");
const Source Source::WindowSystem = Source(1, "GL_DEBUG_SOURCE_WINDOW_SYSTEM");
const Source Source::ShaderCompiler = Source(2, "GL_DEBUG_SOURCE_SHADER_COMPILER");
const Source Source::ThirdParty = Source(3, "GL_DEBUG_SOURCE_THIRD_PARTY");
const Source Source::Application = Source(4, "GL_DEBUG_SOURCE_APPLICATION");
const Source Source::Other = Source(5, "GL_DEBUG_SOURCE_OTHER");
允许像
这样的东西Source firstSource = GetSourceFromSomewhere();
Source secondSource = GetSourceFromElsewhere();
if (firstSource != secondSource)
{
std::cerr << "Sources are not equal: " << firstSource.ToString()
<< " and: " << secondSource.ToString();
}
else if (firstSource == Source::Other)
{
std::cerr << "First source cannot be Other";
}