Don't define static members in a header. You'll introduce the definition into each TU that #include
s the header.
Define them in one TU instead; the easiest way to do this is in a .cpp file.
Question
I tried implementing traits in C++ the first time, but I'm getting linking errors for multiple defined symbols.
error LNK2005: "public: static class std::unordered_map<std::string, std::string> const ManagerTrait<struct Specialized>::Fields"
error LNK2005: "public: static class std::unordered_map<std::string, std::string> const ManagerTrait<struct Specialized>::Fields"
error LNK2005: "public: static class std::unordered_map<std::string, std::string> const ManagerTrait<struct Specialized>::Fields"
error LNK2005: "public: static class std::unordered_map<std::string, std::string> const ManagerTrait<struct Specialized>::Fields"
error LNK2005: "public: static class std::unordered_map<std::string, std::string> const ManagerTrait<struct Specialized>::Fields"
error LNK2005: "public: static class std::unordered_map<std::string, std::string> const ManagerTrait<struct Specialized>::Fields"
error LNK1169: one or more multiply defined symbols found
(I simplified the output by removing templated stuff related to std::unordered_map
like std::allocator
, std::hash
, and so on.)
Basically, there is a Manager
class which uses the traits, a default trait class, and some specialized traits. But all specialized traits need access to a nested type of the Manager
class.
manager.h
#pragma once
class Manager
{
class Parameter
{
// ...
};
template <typename T>
void Usage(T* Instance)
{
typedef ManagerTrait<T> Trait;
// access unordered map
for(auto i : Trait::Fields) { /* ... */ }
// access function
Parameter parameter;
Trait::Function(Instance, ¶meter);
}
}
// would like to move that in dedicated manager/trait.h
template <typename T>
struct ManagerTrait;
specialized.h
#pragma once
#include "manager.h"
class Specialized
{
// ...
};
// would like to move in a dedicated specialized/trait.h
template <>
struct ManagerTrait<Specialized>
{
// define unordered map
static const unordered_map<string, string> Fields;
// define function
static void Function(Specialized *Instance, Manager::Parameter *Parameter)
{
// ...
}
};
// populate unordered map
const unordered_map<string, string> ManagerTrait<Specialized>::Fields = []{
unordered_map<string, string> fields;
// insert some elements
// ...
return fields;
}();
(I removed the occurances of the namespace std::
to make the code more readable.)
How do I need to organize my code files and includes to get it to work?
La solution
Don't define static members in a header. You'll introduce the definition into each TU that #include
s the header.
Define them in one TU instead; the easiest way to do this is in a .cpp file.