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()はよろしくないか