[英]How to iterate over enumerators of an enum class?
有沒有辦法用枚舉enum class
的枚舉器初始化容器(例如std::unordered_set<char>
)?
我有這個 class:
#include <iostream>
#include <unordered_set>
class Foo
{
public:
inline static const std::unordered_set<char> chars_for_drawing { '/', '\\', '|', '-' };
};
int main( )
{
for ( const char ch : Foo::chars_for_drawing )
{
std::cout << ch << ' ';
}
}
但我希望用枚舉器初始化chars_for_drawing
集:
#include <iostream>
#include <unordered_set>
class Foo
{
public:
enum class AllowedChars : char
{
ForwardSlash = '/',
BackSlash = '\\',
VerticalSlash = '|',
Dash = '-'
};
// inline static const std::unordered_set<char> chars_for_drawing { '/', '\\', '|', '-' }; // not like this
inline static const std::unordered_set<char> chars_for_drawing {
static_cast<char>( AllowedChars::ForwardSlash ),
static_cast<char>( AllowedChars::BackSlash ),
static_cast<char>( AllowedChars::VerticalSlash ),
static_cast<char>( AllowedChars::Dash )
};
};
int main( )
{
for ( const char ch : Foo::chars_for_drawing )
{
std::cout << ch << ' ';
}
}
可以看出,第二種方法有點混亂。 有沒有辦法遍歷枚舉器並將它們分配給unordered_set
? 也許通過使用 lambda?
不,沒有直接的方法。 人們經常忘記的一件事:枚舉值的范圍由其基礎類型決定。 枚舉器只是一些命名常量。 關於迭代枚舉器你的枚舉:
enum class AllowedChars : char
{
ForwardSlash = '/',
BackSlash = '\\',
VerticalSlash = '|',
Dash = '-'
};
有助於進行盡可能多的迭代
struct {
char value;
static const char ForwardSlash = '/';
static const char BackSlash = '\\';
static const char VerticalSlash = '|';
static const char Dash = '-';
};
確實:一點也不。
當枚舉器具有連續的值並且有時使用的技巧是使用特殊的枚舉器來表示“大小”時,情況就不同了:
enum class AllowedChars : char
{
ForwardSlash,
BackSlash,
VerticalSlash,
Dash,
SIZE
};
int main() {
for (int i=0;i< static_cast<int>(AllowedChars::SIZE); ++i){
std::cout << i;
}
}
僅此一點就有點傻,因為到實際字符的映射丟失了。 但是,它可以由數組提供:
#include <iostream>
enum class AllowedCharNames : char
{
ForwardSlash,
BackSlash,
VerticalSlash,
Dash,
SIZE
};
char AllowedChars[] = {'/','\\','|','-'};
int main() {
std::cout << AllowedChars[static_cast<size_t>(AllowedCharNames::Dash)];
for (int i=0;i< static_cast<int>(AllowedCharNames::SIZE); ++i){
std::cout << AllowedChars[i];
}
}
TL;DR 重新考慮枚舉是否是適合該工作的工具。 枚舉通常被高估了它們真正能做什么。 有時不是枚舉是更好的選擇。
在 C++ 中, enum
和enum class
不提供您想要的那種功能。
您可以自己實現該功能。 有相當多的樣板,但它可能是值得的,因為它會使調用站點更容易使用。
根據enum
或enum class
的枚舉定義,實現例程可以適應帶有間隙的序列。
這是一個示例,使用簡單的enum class
,沒有間隙。
#include <iostream>
#include <stdexcept>
#include <utility>
using std::cout;
using std::logic_error;
using std::ostream;
using std::underlying_type_t;
namespace {
enum class Lorem {
ipsum, dolor, sit, amet, consectetur, adipiscing
};
auto Lorem_first() -> Lorem { return Lorem::ipsum; }
auto Lorem_last() -> Lorem { return Lorem::adipiscing; }
auto operator<<(ostream& out, Lorem e) -> ostream& {
switch(e) {
#define CASE(x) case Lorem::x: return out << #x
CASE(ipsum);
CASE(dolor);
CASE(sit);
CASE(amet);
CASE(consectetur);
CASE(adipiscing);
#undef CASE
}
throw logic_error("operator<< unknown Lorem");
}
auto operator+(Lorem e) -> underlying_type_t<decltype(e)> {
return static_cast<underlying_type_t<decltype(e)>>(e);
}
auto operator++(Lorem& e) -> Lorem& {
if (e == Lorem_last()) throw logic_error("operator++(Lorem&)");
e = static_cast<Lorem>(+e + 1);
return e;
}
class Lorem_Range {
bool done = false;
Lorem iter = Lorem_first();
public:
auto begin() const -> Lorem_Range const& { return *this; }
auto end() const -> Lorem_Range const& { return *this; }
auto operator*() const -> Lorem { return iter; }
bool operator!=(Lorem_Range const&) const { return !done; }
void operator++() {
if (done) {
throw logic_error("Lorem_Range::operator++");
}
if (iter == Lorem_last()) {
done = true;
} else {
++iter;
}
}
};
} // anon
int main() {
for (auto e : Lorem_Range()) {
cout << +e << ", " << e << "\n";
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.