c++ - Visual Studio 2013: linker errors with custom enumerations? -
i'm using following code, written james mcnellis, simplify declaring more-functional c++2011 enums:
#pragma once #include <stdexcept> #include <boost/preprocessor.hpp> #include <vector> // internal helper provide partial specialization checked_enum_cast template <typename target, typename source> struct checked_enum_cast_impl; // exception thrown 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 declare case labels in checked cast function #define x_define_safe_cast_case(r, data, elem) case elem: // how this? question asked on stackoverflow 11/30/14 -- check again soon. #define x_add_to_toret(r, data, elem) toret.push_back(elem) // defines enumeration checked cast function. // name name of enumeration defined // enumerators preprocessing sequence of enumerators 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)}; \ };
when declare enumeration (the syntax denum(system_states, (loading)(running)(finished));, example), membersof() generates linker error whenever file containing declaration linked multiple objects -- even, example, main.obj , someclass.obj. specific error texts:
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) 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) defined in controller.obj 1>c:\users\username\documents\membersof investigation\debug\membersof investigation.exe : fatal error lnk1169: 1 or more multiply defined symbols found
i know worked couple of months ago, before installed sfml on system, don't think it's cause; reproduced problem in testbed project i'm not linking sfml.
other things declared in header uses above enums, , other uses of boost, work properly.
you should mark memberof
inline
. other option mark static
(as mentioned in comment @simon). link, potentially create copy of memberof
in each compilation unit uses function. declaring memberof
inline
instead should force emitted functions merged 1 linker.
the reason should because believe behavior implementation-defined. in practice, believe above true major implementations, including msvc.
Comments
Post a Comment