scoped enum
enum_typeと名前をつけたenumを内部にもつstructを渡すだけでscoped_enumにする。0xが欲しいけど使えない人のため。
// Copyright hotwatermorning 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef HWM_SCOPED_ENUM_HPP #define HWM_SCOPED_ENUM_HPP //! @file #include <boost/static_assert.hpp> #include <boost/operators.hpp> #include <boost/type_traits/is_enum.hpp> namespace hwm { //! @tparam enum_base has an enum type which named enum_type. template<typename enum_base> struct scoped_enum : enum_base , boost::equality_comparable<scoped_enum<enum_base> , boost::equality_comparable<scoped_enum<enum_base>, typename enum_base::enum_type> > { typedef scoped_enum<enum_base> this_type; typedef typename enum_base::enum_type enum_type; BOOST_STATIC_ASSERT(boost::is_enum<enum_type>::value); scoped_enum() : value_() {} scoped_enum(enum_type value) : value_(value) {} template<typename T> operator T() const { return value_; } bool operator== (this_type const &rhs) const { return value_ == rhs.value_; } bool operator== (enum_type const rhs) const { return value_ == rhs; } void swap(this_type &rhs) throw() { enum_type tmp = value_; value_ = rhs.value_; rhs.value_ = tmp; } private: enum_type value_; }; template<typename T> void swap(scoped_enum<T> &lhs, scoped_enum<T> &rhs) { lhs.swap(rhs); } } //namespace hwm #endif //HWM_SCOPED_ENUM_HPP
scoped_enumのテスト
// Copyright hotwatermorning 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include <boost/test/minimal.hpp> #include "./scoped_enum.hpp" namespace color_detail { struct color_enum_base1 { enum enum_type { red, green, blue }; }; struct color_enum_base2 { enum enum_type { cyan, magenta, yellow }; }; typedef hwm::scoped_enum<color_enum_base1> color1; typedef hwm::scoped_enum<color_enum_base2> color2; } //namespace color_detail int test_main(int, char**) { typedef color_detail::color1 color1; typedef color_detail::color2 color2; { color1 const c1 = color1::red; //construct color1 const c1_copy = c1; //copy-construct color1 c1_assign; c1_assign = c1; //assignment //swap color1 c1_swap1 = color1::green; color1 c1_swap2 = color1::blue; swap(c1_swap1, c1_swap2); BOOST_CHECK(c1_swap1 == color1::blue); BOOST_CHECK(c1_swap2 == color1::green); //color2 const c2 = color1::red; //expected compilation error //color2 const c2_copy = c1; //expected compilation error //color2 const c2_assign = c1; //expected compilation error color2 c2_swap1 = color2::cyan; //swap(c1_swap1, c2_swap1); //expected compilation error } { color1 const c1 = color1::red; //int conversion int const n1 = c1; //not int -> color1 //color1 const c1_ = n1; //expected compilation error } { color1 const c1_red = color1::red; color1 const c1_green = color1::green; //comparison with same type BOOST_CHECK(c1_red == c1_green); BOOST_CHECK(!(c1_red == c1_green)); BOOST_CHECK(!(c1_red != c1_green)); BOOST_CHECK(c1_red != c1_green); //comparison with base enum BOOST_CHECK( c1_red == color1::red ); BOOST_CHECK(!(c1_red == color1::green)); BOOST_CHECK(!(c1_red != color1::red )); BOOST_CHECK( c1_red != color1::green ); BOOST_CHECK( color1::red == c1_red ); BOOST_CHECK(!(color1::green == c1_red)); BOOST_CHECK(!(color1::red != c1_red)); BOOST_CHECK( color1::green != c1_red ); //comparison with another type //BOOST_CHECK(c1_red == 1); //expected compilation error //BOOST_CHECK(!(c1_red == 2)); //expected compilation error //BOOST_CHECK(!(c1_red != 1)); //expected compilation error //BOOST_CHECK(c1_red != 2); //expected compilation error //BOOST_CHECK(1 == c1_red); //expected compilation error //BOOST_CHECK(!(2 == c1_red)); //expected compilation error //BOOST_CHECK(!(1 != c1_red)); //expected compilation error //BOOST_CHECK(2 != c1_red); //expected compilation error color2 const c2_cyan = color2::cyan; //BOOST_CHECK(c1_red == c2_cyan); //expected compilation error //BOOST_CHECK(c1_red != c2_cyan); //expected compilation error } { //just enum value comparison BOOST_CHECK(color1::red != color1::green); BOOST_CHECK(color1::red != color2::cyan); //unfortunately compilation passed...(gcc will issue a warning). } return 0; }
追記:
0xだとenumからintの暗黙の変換無くなるから、operator T()はよろしくないか