0

object.h

#ifndef TESTFACTORYMETHOD_OBJECT_H
#define TESTFACTORYMETHOD_OBJECT_H

#include <string>
#include <unordered_map>
#include <functional>
class Object;
using RegistryFormatMap = std::unordered_map<std::string, std::string>;
using RegistryConstructorMap = std::unordered_map<std::string, std::function<Object*(const std::string &)>>;

class Object {
public:
    static RegistryFormatMap registryFormatMap;
    static RegistryConstructorMap registryConstructorMap;
private:

};


#endif //TESTFACTORYMETHOD_OBJECT_H

apple.h

#ifndef TESTFACTORYMETHOD_APPLE_H
#define TESTFACTORYMETHOD_APPLE_H

#include "object.h"
class Apple : public Object{
public:
    constexpr static char m_name[6] = "Apple";
    std::string m_test_val;
    class Factory {
    public:
        Factory(){
            std::string temp = m_name;
            Object::registryFormatMap[temp] = "test_apple";
            Object::registryConstructorMap[temp] = ([](const std::string &in) -> Apple * { return new Apple(in); });
        }
    };
    static Factory factory;
    explicit Apple(const std::string& str) {
        m_test_val = str;
    }
private:
};


#endif //TESTFACTORYMETHOD_APPLE_H

main.cpp

#include <iostream>

#include "object.h"

int main() {
    for(const std::pair<std::string, std::string>& pair : Object::registryFormatMap) {
        std::cout << pair.second << std::endl;
    }
    return 0;
}

I get the following error

:main.cpp:(.rdata$.refptr._ZN6Object17registryFormatMapB5cxx11E[.refptr._ZN6Object17registryFormatMapB5cxx11E]+0x0): undefined reference to `Object::registryFormatMap[abi:cxx11]'

I'm using mingw64 on windows to compile. I'm attempting to follow the factory method pattern found here but in a way such that I can expand it latter into a macro that doesn't require extensions of object to have to manually enter any of the boiler plate code. I think its possible that Object::registryFormatMap is not initialized but then I would expect run-time errors, not compile time errors.

I'm trying to make two maps, a string format map and a lambda pointer to a constructor map to allow classes to both be initialized and give what they need to be initialized via string format to some external function. In a separate code base I have a lot of these classes, and I'm trying to make it such that I don't have to edit multiple files every-time I add a new class that fits the "Object" format, previously I was using manually created unordered_maps.

Krupip
  • 4,404
  • 2
  • 32
  • 54
  • The linker message is very clear. You need to define `Object::registryFormatMap`. You will also need to define `Object::registryConstructorMap` once you start using it. – R Sahu Mar 23 '18 at 20:29
  • @RSahu um what? You are going to have to be a lot more specific than that, I clearly define `static RegistryFormatMap registryFormatMap` in my code example.... – Krupip Mar 23 '18 at 20:31
  • It is answered at the bottom of this answer: https://stackoverflow.com/a/12574407/487892 – drescherjm Mar 23 '18 at 20:34
  • What you have is a declaration, not a definition. – R Sahu Mar 23 '18 at 20:35
  • @RSahu "C++11 allows initialization inside the class for all static const data members." how would I get that to work here if I'm trying to get it to use the default constructor? – Krupip Mar 23 '18 at 20:36
  • This has nothing to do with a constructor. Just define the static members in your .cpp file. – drescherjm Mar 23 '18 at 20:37
  • @RSahu also https://blog.noctua-software.com/object-factory-c++.html does the exact same thing I'm doing and some how gets away with it... – Krupip Mar 23 '18 at 20:38
  • 1
    Here is the part you miss from that example `static klass##Factory global_##klass##Factory;` – drescherjm Mar 23 '18 at 20:39
  • @snb, Looks like you missed the line `static klass##Factory global_##klass##Factory;` from that page. – R Sahu Mar 23 '18 at 20:40
  • @RSahu no I'm talking about `static map factories;` – Krupip Mar 23 '18 at 20:40
  • 1
    @snb, It seems the code posted on that site is incomplete. – R Sahu Mar 23 '18 at 20:45

0 Answers0