enum support had been incomplete.
This fix made enum support complete.

Replaced int with auto on c++11 scoped enum.
Replaced template specializations with function overloads on operator<< and operator>> for enum.

enum can convert to object with and without zone.

When you want to adapt enum, you need to write as follows:

// NOT msgpack.hpp

enum yourenum {
    elem
};

MSGPACK_ADD_ENUM(yourenum);

// msgpack.hpp should be included after MSGPACK_ADD_ENUM(...)

int main() {
    msgpack::object obj(yourenum::elem);
}
This commit is contained in:
Takatoshi Kondo 2015-01-31 21:59:21 +09:00
parent 978e6b9057
commit c4fb47c00d
8 changed files with 269 additions and 76 deletions

View File

@ -20,6 +20,7 @@
#include "msgpack/versioning.hpp" #include "msgpack/versioning.hpp"
#include "msgpack/adaptor/msgpack_tuple_fwd.hpp" #include "msgpack/adaptor/msgpack_tuple_fwd.hpp"
#include "msgpack/adaptor/int_fwd.hpp"
#include "msgpack/object_fwd.hpp" #include "msgpack/object_fwd.hpp"
#define MSGPACK_DEFINE(...) \ #define MSGPACK_DEFINE(...) \
@ -42,7 +43,6 @@
#define MSGPACK_ADD_ENUM(enum) \ #define MSGPACK_ADD_ENUM(enum) \
namespace msgpack { \ namespace msgpack { \
MSGPACK_API_VERSION_NAMESPACE(v1) { \ MSGPACK_API_VERSION_NAMESPACE(v1) { \
template <> \
inline object const& operator>> (object const& o, enum& v) \ inline object const& operator>> (object const& o, enum& v) \
{ \ { \
int tmp; \ int tmp; \
@ -50,7 +50,10 @@
v = static_cast<enum>(tmp); \ v = static_cast<enum>(tmp); \
return o; \ return o; \
} \ } \
template <> \ inline void operator<< (object& o, const enum& v) \
{ \
o << static_cast<int>(v); \
} \
inline void operator<< (object::with_zone& o, const enum& v) \ inline void operator<< (object::with_zone& o, const enum& v) \
{ \ { \
o << static_cast<int>(v); \ o << static_cast<int>(v); \

View File

@ -20,6 +20,7 @@
#include "msgpack/versioning.hpp" #include "msgpack/versioning.hpp"
#include "msgpack/adaptor/msgpack_tuple_fwd.hpp" #include "msgpack/adaptor/msgpack_tuple_fwd.hpp"
#include "msgpack/adaptor/int_fwd.hpp"
#include "msgpack/object_fwd.hpp" #include "msgpack/object_fwd.hpp"
#define MSGPACK_DEFINE(...) \ #define MSGPACK_DEFINE(...) \
@ -42,7 +43,6 @@
#define MSGPACK_ADD_ENUM(enum) \ #define MSGPACK_ADD_ENUM(enum) \
namespace msgpack { \ namespace msgpack { \
MSGPACK_API_VERSION_NAMESPACE(v1) { \ MSGPACK_API_VERSION_NAMESPACE(v1) { \
template <> \
inline object const& operator>> (object const& o, enum& v) \ inline object const& operator>> (object const& o, enum& v) \
{ \ { \
int tmp; \ int tmp; \
@ -50,7 +50,10 @@
v = static_cast<enum>(tmp); \ v = static_cast<enum>(tmp); \
return o; \ return o; \
} \ } \
template <> \ inline void operator<< (object& o, const enum& v) \
{ \
o << static_cast<int>(v); \
} \
inline void operator<< (object::with_zone& o, const enum& v) \ inline void operator<< (object::with_zone& o, const enum& v) \
{ \ { \
o << static_cast<int>(v); \ o << static_cast<int>(v); \

View File

@ -47,18 +47,21 @@
#define MSGPACK_ADD_ENUM(enum) \ #define MSGPACK_ADD_ENUM(enum) \
namespace msgpack { \ namespace msgpack { \
MSGPACK_API_VERSION_NAMESPACE(v1) { \ MSGPACK_API_VERSION_NAMESPACE(v1) { \
template <> \
inline object const& operator>> (object const& o, enum& v) \ inline object const& operator>> (object const& o, enum& v) \
{ \ { \
int tmp; \ std::underlying_type<enum>::type tmp; \
o >> tmp; \ o >> tmp; \
v = static_cast<enum>(tmp); \ v = static_cast<enum>(tmp); \
return o; \ return o; \
} \ } \
template <> \ inline void operator<< (object& o, const enum& v) \
{ \
auto tmp = static_cast<std::underlying_type<enum>::type>(v); \
o << tmp; \
} \
inline void operator<< (object::with_zone& o, const enum& v) \ inline void operator<< (object::with_zone& o, const enum& v) \
{ \ { \
int tmp = static_cast<std::underlying_type<enum>::type>(v); \ auto tmp = static_cast<std::underlying_type<enum>::type>(v); \
o << tmp; \ o << tmp; \
} \ } \
namespace detail { \ namespace detail { \

View File

@ -1,6 +1,24 @@
#include <msgpack.hpp> #include <msgpack_fwd.hpp>
#include <gtest/gtest.h> #include <gtest/gtest.h>
class enum_member {
public:
enum_member() : flag(A) { }
enum flags_t {
A = 0,
B = 1
};
flags_t flag;
MSGPACK_DEFINE(flag);
};
MSGPACK_ADD_ENUM(enum_member::flags_t);
#include <msgpack.hpp>
class compatibility { class compatibility {
public: public:
compatibility() : str1("default"), str2("default") { } compatibility() : str1("default"), str2("default") { }
@ -43,23 +61,6 @@ TEST(convert, compatibility_more)
EXPECT_EQ("mpio", to.str2); EXPECT_EQ("mpio", to.str2);
} }
class enum_member {
public:
enum_member() : flag(A) { }
enum flags_t {
A = 0,
B = 1
};
flags_t flag;
MSGPACK_DEFINE(flag);
};
MSGPACK_ADD_ENUM(enum_member::flags_t);
TEST(convert, enum_member) TEST(convert, enum_member)
{ {
enum_member src; enum_member src;
@ -73,4 +74,3 @@ TEST(convert, enum_member)
EXPECT_EQ(enum_member::B, to.flag); EXPECT_EQ(enum_member::B, to.flag);
} }

View File

@ -1,4 +1,4 @@
#include "msgpack.hpp" #include <msgpack_fwd.hpp>
#include <cmath> #include <cmath>
#include <string> #include <string>
@ -15,6 +15,31 @@
#include "config.h" #include "config.h"
#endif #endif
class TestEnumMemberClass
{
public:
TestEnumMemberClass()
: t1(STATE_A), t2(STATE_B), t3(STATE_C) {}
enum TestEnumType {
STATE_INVALID = 0,
STATE_A = 1,
STATE_B = 2,
STATE_C = 3
};
TestEnumType t1;
TestEnumType t2;
TestEnumType t3;
MSGPACK_DEFINE(t1, t2, t3);
};
MSGPACK_ADD_ENUM(TestEnumMemberClass::TestEnumType);
#include <msgpack.hpp>
using namespace std; using namespace std;
const unsigned int kLoop = 1000; const unsigned int kLoop = 1000;
@ -488,27 +513,6 @@ TEST(MSGPACK_USER_DEFINED, simple_buffer_class_new_to_old)
} }
} }
class TestEnumMemberClass
{
public:
TestEnumMemberClass()
: t1(STATE_A), t2(STATE_B), t3(STATE_C) {}
enum TestEnumType {
STATE_INVALID = 0,
STATE_A = 1,
STATE_B = 2,
STATE_C = 3
};
TestEnumType t1;
TestEnumType t2;
TestEnumType t3;
MSGPACK_DEFINE(t1, t2, t3);
};
MSGPACK_ADD_ENUM(TestEnumMemberClass::TestEnumType);
TEST(MSGPACK_USER_DEFINED, simple_buffer_enum_member) TEST(MSGPACK_USER_DEFINED, simple_buffer_enum_member)
{ {
TestEnumMemberClass val1; TestEnumMemberClass val1;

View File

@ -1,4 +1,4 @@
#include "msgpack.hpp" #include <msgpack_fwd.hpp>
#include <gtest/gtest.h> #include <gtest/gtest.h>
@ -6,12 +6,36 @@
#include "config.h" #include "config.h"
#endif #endif
#if !defined(MSGPACK_USE_CPP03)
class TestEnumClassMemberClass
{
public:
TestEnumClassMemberClass()
: t1(TestEnumClassType::STATE_A), t2(TestEnumClassType::STATE_B), t3(TestEnumClassType::STATE_C) {}
enum class TestEnumClassType:long {
STATE_INVALID = 0,
STATE_A = 1,
STATE_B = 2,
STATE_C = 3
};
TestEnumClassType t1;
TestEnumClassType t2;
TestEnumClassType t3;
MSGPACK_DEFINE(t1, t2, t3);
};
MSGPACK_ADD_ENUM(TestEnumClassMemberClass::TestEnumClassType);
#include <msgpack.hpp>
using namespace std; using namespace std;
const unsigned int kLoop = 10000; const unsigned int kLoop = 10000;
const unsigned int kElements = 100; const unsigned int kElements = 100;
#if !defined(MSGPACK_USE_CPP03)
// C++11 // C++11
@ -150,29 +174,6 @@ TEST(MSGPACK_STL, simple_buffer_unordered_multiset)
} }
} }
class TestEnumClassMemberClass
{
public:
TestEnumClassMemberClass()
: t1(TestEnumClassType::STATE_A), t2(TestEnumClassType::STATE_B), t3(TestEnumClassType::STATE_C) {}
enum class TestEnumClassType:long {
STATE_INVALID = 0,
STATE_A = 1,
STATE_B = 2,
STATE_C = 3
};
TestEnumClassType t1;
TestEnumClassType t2;
TestEnumClassType t3;
MSGPACK_DEFINE(t1, t2, t3);
};
MSGPACK_ADD_ENUM(TestEnumClassMemberClass::TestEnumClassType);
TEST(MSGPACK_USER_DEFINED, simple_buffer_enum_class_member) TEST(MSGPACK_USER_DEFINED, simple_buffer_enum_class_member)
{ {
TestEnumClassMemberClass val1; TestEnumClassMemberClass val1;

View File

@ -1,6 +1,43 @@
#include <msgpack.hpp> #include <msgpack_fwd.hpp>
#include <gtest/gtest.h> #include <gtest/gtest.h>
enum enum_test {
elem
};
MSGPACK_ADD_ENUM(enum_test);
struct outer_enum {
enum enum_test {
elem
};
};
MSGPACK_ADD_ENUM(outer_enum::enum_test);
#if !defined(MSGPACK_USE_CPP03)
enum class enum_class_test {
elem
};
MSGPACK_ADD_ENUM(enum_class_test);
struct outer_enum_class {
enum class enum_class_test {
elem
};
};
MSGPACK_ADD_ENUM(outer_enum_class::enum_class_test);
#endif // !defined(MSGPACK_USE_CPP03)
#include <msgpack.hpp>
struct myclass { struct myclass {
myclass() : num(0), str("default") { } myclass() : num(0), str("default") { }
@ -256,3 +293,54 @@ TEST(object, construct_primitive)
EXPECT_EQ(msgpack::type::BOOLEAN, obj_bool.type); EXPECT_EQ(msgpack::type::BOOLEAN, obj_bool.type);
EXPECT_EQ(true, obj_bool.via.boolean); EXPECT_EQ(true, obj_bool.via.boolean);
} }
TEST(object, construct_enum)
{
msgpack::object obj(elem);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
#if !defined(MSGPACK_USE_CPP03)
TEST(object, construct_enum_newstyle)
{
msgpack::object obj(enum_test::elem);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
#endif // !defined(MSGPACK_USE_CPP03)
TEST(object, construct_enum_outer)
{
msgpack::object obj(outer_enum::elem);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
#if !defined(MSGPACK_USE_CPP03)
TEST(object, construct_enum_outer_newstyle)
{
msgpack::object obj(outer_enum::enum_test::elem);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
TEST(object, construct_class_enum)
{
msgpack::object obj(enum_class_test::elem);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
TEST(object, construct_class_enum_outer)
{
msgpack::object obj(outer_enum_class::enum_class_test::elem);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
#endif // !defined(MSGPACK_USE_CPP03)

View File

@ -1,4 +1,4 @@
#include <msgpack.hpp> #include <msgpack_fwd.hpp>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <cmath> #include <cmath>
@ -6,6 +6,43 @@
#include "config.h" #include "config.h"
#endif #endif
enum enum_test {
elem
};
MSGPACK_ADD_ENUM(enum_test);
struct outer_enum {
enum enum_test {
elem
};
};
MSGPACK_ADD_ENUM(outer_enum::enum_test);
#if !defined(MSGPACK_USE_CPP03)
enum class enum_class_test {
elem
};
MSGPACK_ADD_ENUM(enum_class_test);
struct outer_enum_class {
enum class enum_class_test {
elem
};
};
MSGPACK_ADD_ENUM(outer_enum_class::enum_class_test);
#endif // !defined(MSGPACK_USE_CPP03)
#include <msgpack.hpp>
using namespace std; using namespace std;
const unsigned int kLoop = 1000; const unsigned int kLoop = 1000;
@ -615,8 +652,62 @@ TEST(object_with_zone, user_defined)
EXPECT_EQ(v1.s, v2.s); EXPECT_EQ(v1.s, v2.s);
} }
TEST(object_with_zone, construct_enum)
{
msgpack::zone z;
msgpack::object obj(elem, z);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
#if !defined(MSGPACK_USE_CPP03) #if !defined(MSGPACK_USE_CPP03)
TEST(object_with_zone, construct_enum_newstyle)
{
msgpack::zone z;
msgpack::object obj(enum_test::elem, z);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
#endif // !defined(MSGPACK_USE_CPP03)
TEST(object_with_zone, construct_enum_outer)
{
msgpack::zone z;
msgpack::object obj(outer_enum::elem, z);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
#if !defined(MSGPACK_USE_CPP03)
TEST(object_with_zone, construct_enum_outer_newstyle)
{
msgpack::zone z;
msgpack::object obj(outer_enum::enum_test::elem, z);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
TEST(object_with_zone, construct_class_enum)
{
msgpack::zone z;
msgpack::object obj(enum_class_test::elem, z);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
TEST(object_with_zone, construct_class_enum_outer)
{
msgpack::zone z;
msgpack::object obj(outer_enum_class::enum_class_test::elem, z);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
EXPECT_EQ(elem, obj.via.u64);
}
TEST(object_with_zone, array) TEST(object_with_zone, array)
{ {
typedef array<int, kElements> test_t; typedef array<int, kElements> test_t;