0

I'm trying to create an autoload class system using class mapping as specified in best answere of this post:

Is there a way to instantiate objects from a string holding their class name?

so i've created this code based on my needs:

// ScriptLoader.h
template<class TScript> void createScript() { 
    new TScript; 
}

struct ScriptFactory {
public:
    typedef void(*ScriptCreatorFunc)();
    typedef std::map<std::string,ScriptCreatorFunc> ScriptCreatorStorage;

    static ScriptCreatorStorage ScriptCreators;

    static bool RegisterCreator(std::string const& s,ScriptCreatorFunc creator)
    {
        ASSERT(ScriptCreators.find(s) == ScriptCreators.end());   // prevent registering the same script twice
        ScriptCreators.insert(std::make_pair(s,creator));
        return true;
    }
};

template<class TScript>
struct ScriptReg : ScriptFactory { 
    ScriptReg(std::string const& s) { 
        ScriptFactory::RegisterCreator(s,&createScript<TScript>);
    }
};

class ScriptLoader {
public:
    static void AddScripts()
    {
        for (ScriptFactory::ScriptCreatorStorage::iterator itr = ScriptFactory::ScriptCreators.begin(); itr != ScriptFactory::ScriptCreators.end(); ++itr)
            itr->second();
    }    
};

#define REGISTER_DEC_TYPE(NAME) \
    static ScriptReg<NAME> reg

#define REGISTER_DEF_TYPE(NAME) \
    ScriptReg<NAME> NAME::reg(#NAME)


// ScriptLoader.cpp
ScriptFactory::ScriptCreatorStorage ScriptFactory::ScriptCreators;

// foo.cpp
class foo:
{
    public:

        foo()
        {
                /* code */
        }

    private:
        REGISTER_DEC_TYPE(foo);
};

REGISTER_DEF_TYPE(foo);

and of course i've defined REGISTER_DEC_TYPE in a foo class and at bottom of foo.cpp file i've put: REGISTER_DEF_TYPE(foo) ... ( AddScripts function instead is called by main program so it's normally linked in binaries )

it compiles well but when i try to debug , i cannot set breakpoints in visual studio that shows this tip: "No executable code is associated with this line. Possible causes include: preprocessor directive or compiler/linker optimization"

and in foo.cpp it shows: "any symbol has been loaded for this document"

so i guess the compiler don't find any "normal" call to these functions/classes removing them from the binary code.

Is there any way to avoid this kind of optimization? i'm finding a crossplatform solution to this problem.

thanks in advance

Community
  • 1
  • 1
Joseph
  • 1,029
  • 13
  • 26
  • 1
    Can you explain exactly which line(s) in your code you are setting breakpoints at? – Mats Petersson Feb 22 '13 at 11:00
  • any lines of RegisterCreator and createScript function or everywhere in foo class of foo.cpp ( AddScripts function instead is called by main process so it's normally linked by compiler ) – Joseph Feb 22 '13 at 12:36
  • Are you sure you can compile it? static `ScriptReg reg` requires the default ctor, but there is only one that takes `std::string const& s` – Grigorii Chudnov Feb 22 '13 at 12:44
  • yes it compiled, anyway i've cleaned a bit the code and edited first post , it continues to compile but doesn't work yet..foo class and other pieces of code are not linked in binaries. – Joseph Feb 22 '13 at 13:46

1 Answers1

2

Deadstripping is a common problem with factory code. What you usually have to do is have a function somewhere that uses all of your types. It's ugly but unfortunately there are no particularly elegant portable solutions.

Jack Aidley
  • 19,439
  • 7
  • 43
  • 70
  • so is it required to call all classes somewhere in main process to be registered in map? – Joseph Feb 22 '13 at 14:03
  • Most compilers remove unused symbols (deadstripping) so that you don't end up with unused cruft in your executable. Unfortunately in this case, it's over enthusiastic so, yes, you need to use them. Making all your register calls in a central `register` function will achieve this. – Jack Aidley Feb 22 '13 at 14:37