我正在从事一个高级项目,并且对如何最好地为我的程序实现查找表有疑问。有几个enum class
文件包含enum class
和一个operator<<
重载以将它们输出到std::string
。我们正在使用boost属性树来解析JSON文件,并且默认情况下,解析无法将字符串转换为enum class
。由于我们在程序中的某些时候需要枚举类和字符串,因此实现std::unordered_map
是有意义的。但是,我的问题是如何根据文件放置查找表?
当前,我们的代码有4个枚举类文件,总结如下:
namespace wiregen{
enum class {/* values */}
ostream& operator<<(ostream& os, enum){/*overload code to output enum as a string*/}
}
枚举需要公开,因为它们被多个类使用。我目前已定义它们,并且在枚举头文件中定义了operator <<重载。我的问题是,是否应该将查找表放在enum标头中,进行枚举实现,然后将查找表移到其中,还是其他?
答案 0 :(得分:1)
尽管这只是一个基于设计的问题,但我建议您将地图放置在匿名名称空间中,以便从界面中隐藏它。此方法不需要其他实现文件,因为您可以从括号列表中初始化常量unordered_map
。
// SomeHeader.h
enum class Color {
Red,
Blue,
Green,
Unknown,
};
// Anonymous namespace to hide our implementation
namespace {
std::unordered_map<std::string, Color> const stringToColorMap_ = {
{ "Red", Color::Red },
{ "Blue", Color::Blue },
{ "Green", Color::Green },
};
}
// Public interface
Color colorFromString(std::string const& s) {
auto it = stringToColorMap_.find(s);
if (it != stringToColorMap_.end()) {
return it->second;
}
return Color::Unknown;
}
int main() {
cout << static_cast<int>(colorFromString("Red")) << endl;
cout << static_cast<int>(colorFromString("Blue")) << endl;
}
答案 1 :(得分:0)
作为解决此问题的方法,我发现最好的解决方法是将枚举包装在一个类中,然后将函数作为该类的一部分提供给我想要的功能。我不得不将它们从范围枚举更改为普通枚举,但现在它提供了我们所需的行为。
下面是一个示例
Base.hpp
namespace wiregen{
class Base{
public:
enum baseEnum{
/*removed for brevity*/
};
Base();
constexpr Base(baseEnum b) : val(b){}
bool operator==(Base b) const;
bool operator!=(Base b) const;
operator std::string() const;
void operator = (const std::string &str);
private:
baseEnum val;
};
std::ostream& operator<<(std::ostream& os, const wiregen::Base& b);
}
Base.cpp
namespace{
typedef boost::bimap<wiregen::Base::baseEnum, std::string>BaseTable;
typedef BaseTable::value_type baseString;
BaseTable m_base = boost::assign::list_of<baseString>
/* removed for brevity */
}
namespace wiregen{
Base::Base(){val = baseEnum::invalid;}
bool Base::operator==(Base b) const{return val == b.val;}
bool Base::operator!=(Base b) const{return val != b.val;}
Base::operator std::string() const{
auto it = m_base.left.find(val);
if(it != m_base.left.end()){
return it->second;
}
return "invalid";
}
void Base::operator = (const std::string &str){
auto it = m_base.right.find(boost::algorithm::to_lower_copy(str));
if(it != m_base.right.end()){
val = it->second;
return;
}
std::cerr<<"Failed to assign Base: "<<str<<std::endl;
return;
}
std::ostream& operator<<(std::ostream& os, const Base& b){
os << (std::string)b;
return os;
}
}