gpt4 book ai didi

c++ - Visual Studio 2013 : linker errors with custom enumerations?

转载 作者:行者123 更新时间:2023-11-30 05:40:31 24 4
gpt4 key购买 nike

我正在使用 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));),每当包含声明的文件链接到多个对象——甚至,例如,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 的测试平台项目中重现了这个问题。

在使用上述枚举的 header 中声明的其他内容,以及 boost 的其他用途,都可以正常工作。

最佳答案

您应该标记 MemberOf inline。您的另一个选择是将其标记为 static (如@simon 的评论中所述)。这将链接,但它可能会在使用该函数的每个编译单元中创建 MemberOf 的拷贝。声明 MemberOf inline 而不是 应该 强制链接器将发出的函数合并为一个。

我之所以说应该,是因为我相信这种行为是实现定义的。在实践中,我相信以上内容适用于所有主要实现,包括 MSVC。

关于c++ - Visual Studio 2013 : linker errors with custom enumerations?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31600849/

24 4 0