2013-04-20 7 views
6

循環値を列挙し、値から別の値に変換する適切な関数を実装する最良の方法は何でしょうか?例えば円列挙値の実装

enum class Direction { 
    NORTH, EAST, SOUTH, WEST 
}; 

constexpr Direction left(Direction d) { 
    return (Direction)((std::underlying_type<Directions>::type(d) - 1) % 4); 
} 

はしかし、私はこのエラーが発生しやすく、一般的に読めないと感じています。このタイプの列挙を扱うより適切な方法がありますか?

+0

四に、明示的にそれをスペルをcase switch文?それは最も読みやすいオプションです。 – RichieHindle

+0

LOTSの値が増えたらどうなりますか? – Svalorzen

+0

'left'を' nextCounterclockwise'(あるいは 'nextCCW')に変更すると読みやすくなります:-D – deepmax

答えて

9

あなたは常に行うことができます:

enum class Direction { 
    NORTH, EAST, SOUTH, WEST, NUMBER_OF_DIRECTIONS 
}; 

constexpr Direction left(Direction d) { 
    using ut = std::underlying_type<Direction>::type; 
    return (Direction)((ut(d) + ut(Direction::NUMBER_OF_DIRECTIONS)-1) 
         % ut(Direction::NUMBER_OF_DIRECTIONS)); 
} 

使用例/小テスト:

#include <iostream> 

std::ostream& operator<<(std::ostream& os, Direction d) 
{ 
    switch(d) 
    { 
     case Direction::NORTH: return os << "NORTH"; 
     case Direction::EAST : return os << "EAST"; 
     case Direction::SOUTH: return os << "SOUTH"; 
     case Direction::WEST : return os << "WEST"; 
     default    : return os << "invalid"; 
    } 
} 

int main() 
{ 
    Direction d = Direction::NORTH; 
    for(int i = 0; i < 2*(int)Direction::NUMBER_OF_DIRECTIONS; ++i) 
    { 
     std::cout << d << "\n"; 
     d = left(d); 
    } 
} 

出力:

 
NORTH 
WEST 
SOUTH 
EAST 
NORTH 
WEST 
SOUTH 
EAST 

Live example

+0

追加要素は必要ありません。'%(std :: underlying_type ::タイプ(WEST)+ 1) '。しかし、それでも、それは迅速な修正のように見えますか? – Svalorzen

+1

@Svalorzen:しかし、 'WEST + 1'は人間が読めるものではありません。 'WEST'の後に何かが追加されたらどうなりますか?少なくとも 'NUMBER_OF_DIRECTIONS'でその意図は明確です。 @PeterK。 –

+0

それでも、 'underlying_type'全体を' NUMBER_OF_DIRECTIONS'にする必要があります。かなり長くなるでしょう。 – Svalorzen