kfm*_*e04 65 c++ enums for-loop c++11
我有一个经常出现的代码块,我循环遍历所有成员enum class
.
for
与新的相比,我目前使用的循环看起来非常笨拙range-based for
.
有没有办法利用新的C++ 11功能来减少当前for
循环的详细程度?
我希望改进的当前代码:
enum class COLOR
{
Blue,
Red,
Green,
Purple,
First=Blue,
Last=Purple
};
inline COLOR operator++( COLOR& x ) { return x = (COLOR)(((int)(x) + 1)); }
int main(int argc, char** argv)
{
// any way to improve the next line with range-based for?
for( COLOR c=COLOR::First; c!=COLOR::Last; ++c )
{
// do work
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
换句话说,如果我可以做以下事情会很好:
for( const auto& c : COLOR )
{
// do work
}
Run Code Online (Sandbox Code Playgroud)
def*_*ode 50
我个人不喜欢为++
运算符重载运算符.通常递增枚举值并不真正有意义.所有真正想要的是一种迭代枚举的方法.
下面是一个Enum
支持迭代的泛型类.它功能齐全但不完整.一个真正的实现可以很好地限制对构造函数的访问并添加所有迭代器特征.
#include <iostream>
template< typename T >
class Enum
{
public:
class Iterator
{
public:
Iterator( int value ) :
m_value( value )
{ }
T operator*( void ) const
{
return (T)m_value;
}
void operator++( void )
{
++m_value;
}
bool operator!=( Iterator rhs )
{
return m_value != rhs.m_value;
}
private:
int m_value;
};
};
template< typename T >
typename Enum<T>::Iterator begin( Enum<T> )
{
return typename Enum<T>::Iterator( (int)T::First );
}
template< typename T >
typename Enum<T>::Iterator end( Enum<T> )
{
return typename Enum<T>::Iterator( ((int)T::Last) + 1 );
}
enum class Color
{
Red,
Green,
Blue,
First = Red,
Last = Blue
};
int main()
{
for( auto e: Enum<Color>() )
{
std::cout << ((int)e) << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
use*_*322 35
enum class Color {
blue,
red,
green = 5,
purple
};
const std::array<Color,4> all_colors = {Color::blue, Color::red, Color::green, Color::purple};
Run Code Online (Sandbox Code Playgroud)
然后:
for (Color c : all_colors) {
//...
}
Run Code Online (Sandbox Code Playgroud)
很多时候我这样使用它,我想要一个'none'值:
// Color of a piece on a chess board
enum class Color {
white,
black,
none
};
const std::array<Color,3> colors = {Color::white, Color::black};
template <typename CONTAINER>
bool has_item (CONTAINER const & c, typename CONTAINER::const_reference v) {
return std::find(c.begin(), c.end(), v) != c.end();
}
bool is_valid (Color c) {
return has_item(colors, c) || c == Color::none;
}
bool do_it (Color c) {
assert(has_item(colors, c)); // here I want a real color, not none
// ...
}
bool stop_it (Color c) {
assert(is_valid(c)); // but here I just want something valid
// ...
}
Run Code Online (Sandbox Code Playgroud)
Moo*_*uck 30
使用枚举本身作为迭代器迭代枚举是一个糟糕的想法,我建议在deft_code的答案中使用实际的迭代器.但如果这真的是你想要的:
COLOR operator++(COLOR& x) {
return x = (COLOR)(std::underlying_type<COLOR>::type(x) + 1);
}
COLOR operator*(COLOR c) {
return c;
}
COLOR begin(COLOR r) {
return COLOR::First;
}
COLOR end(COLOR r) {
COLOR l=COLOR::Last;
return ++l;
}
int main() {
//note the parenthesis after COLOR to make an instance
for(const auto& c : COLOR()) {
//do work
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这里工作:http://ideone.com/cyTGD8
extern const COLOR COLORS[(int)COLOR::Last+1];
const COLOR COLORS[] = {COLOR::Blue, COLOR::Red, COLOR::Green, COLOR::Purple};
int main() {
for(const auto& c : COLORS) {
//do work
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如下所示:http://ideone.com/9XadVt
(如果颜色数与数组中的元素数量不匹配,则数组的单独声明和定义会使编译错误.非常简单的安全检查.)
您可能可以通过boost :: mpl做一些聪明的事情,一个粗糙的版本可能看起来像:
#include <typeinfo>
// ---------------------------------------------------------------------------|
// Boost MPL
// ---------------------------------------------------------------------------|
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/iterator_range.hpp>
#include <boost/mpl/range_c.hpp>
namespace mpl = boost::mpl;
using namespace std;
enum class COLOR
{
Blue,
Red,
Green,
Purple,
Last
};
struct enumValPrinter
{
template< typename T >
void operator() (const T&)
{
cout << "enumValPrinter with: " << typeid( T ).name() << " : "
<< T::value << "\n";
}
};
int main(int, char**)
{
typedef mpl::range_c< int, static_cast<int>( COLOR::Blue ),
static_cast<int>( COLOR::Last ) > Colors;
mpl::for_each< Colors >( enumValPrinter() );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我确定您可以遍历 C++ initializer_list 的成员,所以我认为我过去已经这样做了:
enum class Color {Red, Green, Blue};
for (const Color c : {Color::Red, Color::Green, Color::Blue})
{
}
Run Code Online (Sandbox Code Playgroud)
这是否有问题,我不知道,但我认为我会建议它,因为它简洁,但如果有很多颜色就不理想了。
归档时间: |
|
查看次数: |
44858 次 |
最近记录: |