Вопрос

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, &parameter);
    }
}

// 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?

Это было полезно?

Решение

Don't define static members in a header. You'll introduce the definition into each TU that #includes the header.

Define them in one TU instead; the easiest way to do this is in a .cpp file.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top