【发布时间】:2015-07-24 01:42:47
【问题描述】:
我使用以下由 James McNellis 编写的代码来简化声明更多功能的 C++2011 枚举:
#pragma once
#include <stdexcept>
#include <boost/preprocessor.hpp>
#include <vector>
// Internal helper to provide partial specialization for checked_enum_cast
template <typename Target, typename Source>
struct checked_enum_cast_impl;
// Exception thrown by checked_enum_cast on cast failure
struct invalid_enum_cast : std::out_of_range
{
invalid_enum_cast(const char* s)
: std::out_of_range(s) { }
};
// Checked cast function
template <typename Target, typename Source>
Target checked_enum_cast(Source s)
{
return checked_enum_cast_impl<Target, Source>::do_cast(s);
}
// Internal helper to help declare case labels in the checked cast function
#define X_DEFINE_SAFE_CAST_CASE(r, data, elem) case elem:
// How to do this? Question asked on StackOverflow 11/30/14 -- check back again soon.
#define X_ADD_TO_TORET(r, data, elem) ToRet.push_back(elem)
// Defines an enumeration with a checked cast function.
// name is the name of the enumeration to be defined
// enumerators is the preprocessing sequence of enumerators to be defined.
#define DENUM(name, enumerators) \
enum name \
{ \
BOOST_PP_SEQ_ENUM(enumerators) \
}; \
\
template <typename Source> \
struct checked_enum_cast_impl<name, Source> \
{ \
static name cast(Source s) \
{ \
switch (s) \
{ \
BOOST_PP_SEQ_FOR_EACH(X_DEFINE_SAFE_CAST_CASE, 0, enumerators) \
return static_cast<name>(s); \
default: \
throw invalid_enum_cast(BOOST_PP_STRINGIZE(name)); \
} \
return name(); \
} \
}; \
std::vector<name> MembersOf(name AnyItem) { \
return {BOOST_PP_SEQ_ENUM(enumerators)}; \
};
当我用这个声明一个枚举时(例如,语法是 DENUM(SYSTEM_STATES, (Loading)(Running)(Finished));),只要包含声明的文件链接到,MembersOf() 就会生成链接器错误多个对象——甚至例如 main.obj 和 someclass.obj。具体错误文字:
1>main.obj : error LNK2005: "class std::vector<enum SYSTEM_STATES,class std::allocator<enum SYSTEM_STATES> > __cdecl MembersOf(enum SYSTEM_STATES)" (?MembersOf@@YA?AV?$vector@W4SYSTEM_STATES@@V?$allocator@W4SYSTEM_STATES@@@std@@@std@@W4SYSTEM_STATES@@@Z) already defined in Controller.obj
1>UserInputProcessor.obj : error LNK2005: "class std::vector<enum SYSTEM_STATES,class std::allocator<enum SYSTEM_STATES> > __cdecl MembersOf(enum SYSTEM_STATES)" (?MembersOf@@YA?AV?$vector@W4SYSTEM_STATES@@V?$allocator@W4SYSTEM_STATES@@@std@@@std@@W4SYSTEM_STATES@@@Z) already defined in Controller.obj
1>C:\Users\UserName\Documents\MembersOf investigation\Debug\MembersOf investigation.exe : fatal error LNK1169: one or more multiply defined symbols found
我知道这几个月前在我的系统上安装 SFML 之前可以正常工作,但我认为这不是原因;我在一个测试平台项目中重现了这个问题,我什至没有链接到 SFML。
在使用上述枚举的标头中声明的其他内容以及 boost 的其他用途都可以正常工作。
【问题讨论】:
标签: c++ boost visual-studio-2013 enums linker