How to automatically register a class on creation
You can indeed do this using the curiously recursive template idiom. It requires nothing from whoever is extending the class that can't be enforced by the compiler:
template<class T>
struct Animal
{
Animal()
{
reg; //force specialization
}
virtual std::string name() = 0;
static bool reg;
static bool init()
{
T t;
AnimalManager::registerAnimal(t.name());
return true;
}
};
template<class T>
bool Animal<T>::reg = Animal<T>::init();
struct Tiger : Animal<Tiger>
{
virtual std::string name() { return "Tiger"; }
};
In this code, you can only extend Animal
if you specialize it. The constructor forces the static
member reg
to be initialized, which in turn calls the register method.
EDIT: As pointed out by @David Hammen in the comments, you won't be able to have a collection of Animal
objects. However, this can easily be solved by having a non-template class from which the template inherits and use that as a base class, and only use the template for extending.
How to auto register a class when it's defined
Yes, meta classes can do this. A meta class' __new__
method returns the class, so just register that class before returning it.
class MetaClass(type):
def __new__(cls, clsname, bases, attrs):
newclass = super(MetaClass, cls).__new__(cls, clsname, bases, attrs)
register(newclass) # here is your register function
return newclass
class MyClass(object):
__metaclass__ = MetaClass
The previous example works in Python 2.x. In Python 3.x, the definition of MyClass
is slightly different (while MetaClass
is not shown because it is unchanged - except that super(MetaClass, cls)
can become super()
if you want):
#Python 3.x
class MyClass(metaclass=MetaClass):
pass
As of Python 3.6 there is also a new __init_subclass__
method (see PEP 487) that can be used instead of a meta class (thanks to @matusko for his answer below):
class ParentClass:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
register(cls)
class MyClass(ParentClass):
pass
[edit: fixed missing cls
argument to super().__new__()
]
[edit: added Python 3.x example]
[edit: corrected order of args to super(), and improved description of 3.x differences]
[edit: add Python 3.6 __init_subclass__
example]
Automatically Register Class to the Window
One way of doing this would be to create a function for registering a class. [Classes] have a name
property which you can use for registering the name in the global space. This does require you to declare your classes inside of a function but without some kind of code transformation being done before the code hits the browser, it's about the best you can do.
function register(c) { console.log('Registering ' + c.name); window[c.name] = c;}
register(class ClassA { constructor() { console.log('Created ClassA'); }});
register(class ClassB { constructor() { console.log('Created ClassB'); }});
register(class ClassC { constructor() { console.log('Created ClassC'); }});
new ClassA();new ClassB();new ClassC();
Auto register a class when it's defined (but without importing it anywhere)
I feel that your approach is a bit complicated to implement the functionality you want. My suggestion is to you use a strategy like this:
- Name your modules so that the command classes are defined in files named after the commands they implement. For example, the
RebootCommand
class goes into the filecommands/reboot.py
. Every command module defines a top-level variable
command_cls
that contains a reference to the class implementing the command.commands/reboot.py
would therefore contain code like this:class RebootCommand:
def execute(self):
# [...]
command_cls = RebootCommandTo execute a command, you use the
__import__
function to dynamically load your module. YourCommandManager.py
would logically live in a file outside thecommands
directory (which is reserved for command modules) and would be implemented like the following:class CommandManager:
@classmethod
def execute(cls, command, *args, **kw):
# import the command module
commands_mod = __import__("commands", globals(), locals(), [command])
mod = getattr(commands_mod, command)
return mod.command_cls(*args, **kw).execute()
EDIT: Seems I confused the usage of the imp
module. Updated the code to use __import__
.
Automatic registration of derived classes in a factory pattern
Your code looks too complicated to me. Maybe there is a reason that I miss.
You cannot avoid the registration. What you are looking for is registration at compile time, which I think it is not possible. Since you are looking for registration at compile time, it means that you do not need to expose the registration method in interface. So, your client interface should be made of the base class and a creation method:
// { client interface header
class B
{
public:
virtual ~B() = 0 {}
//...
};
B* Create( const char* s );
// } client interface header
A simple creation function:
// { client interface implementation
template< typename T >
B* New()
{
return new T;
}
typedef B* (*PFNew)();
B* Create( const char* s )
{
typedef std::map< string, PFNew > Map;
static Map m;
if ( ! m.size() )
{
m[ D1::Signature() ] = New< D1 >;
m[ D2::Signature() ] = New< D2 >;
//...
}
Map::const_iterator ci = m.find( s );
if ( ci == m.end() )
throw -1;
return ci->second();
}
// } client interface implementation
C# make class auto-register
I have checked with other resources (that are quite knowledgeable about the internals of the CLR and IL) and it seems that this is a hole in the CLR and the C# language. There simply is no direct way of making things automatically happen on assembly load or appdomain preparation. Walking the types and finding the types that I'm interested in is the least bad way.
In fact, attributes aren't always created until some piece of code asks for them, so I can't use an attribute constructor with a type argument to auto-register, either!
This is of course not great, because if there are eight different pieces of code that each have their own kind of registration they want to do, each of those pieces have to iterate through all of the types and do the inspection on their own. The only way around that would be to give up on modularity, and make all of the different "things" that happen to types be centralized to a single walk-all-types loop at the start of the app. Third party libraries (including the MEF) still wouldn't go inside this loop, though, so there's just an unavoidable chunk of overhead here, OR an unavoidable piece of duplication -- my choice, as developer.
Python: How to register all child classes with the father class upon creation
you can use meta classes for that:
class AutoRegister(type):
def __new__(mcs, name, bases, classdict):
new_cls = type.__new__(mcs, name, bases, classdict)
#print mcs, name, bases, classdict
for b in bases:
if hasattr(b, 'register_subclass'):
b.register_subclass(new_cls)
return new_cls
class AbstractClassA(object):
__metaclass__ = AutoRegister
_subclasses = []
@classmethod
def register_subclass(klass, cls):
klass._subclasses.append(cls)
@classmethod
def get_concrete_classes(klass):
return klass._subclasses
class ConcreteClassA1(AbstractClassA):
pass
class ConcreteClassA2(AbstractClassA):
pass
class ConcreteClassA3(ConcreteClassA2):
pass
print AbstractClassA.get_concrete_classes()
I'm personnaly very wary of this kind of magic. Don't put too much of this in your code.
Best way to for C++ types to self register in a list?
You can execute something before main once if a instantiation of a template is made. The trick is to put a static data member into a class template, and reference that from outside. The side effect that static data member triggers can be used to call the register function:
template<typename D>
struct automatic_register {
private:
struct exec_register {
exec_register() {
persistenceSystem::registerPersistableType(
D::getPersister()
);
}
};
// will force instantiation of definition of static member
template<exec_register&> struct ref_it { };
static exec_register register_object;
static ref_it<register_object> referrer;
};
template<typename D> typename automatic_register<D>::exec_register
automatic_register<D>::register_object;
Derive the class you want to be auto-registered from automatic_register<YourClass>
. The register function will be called before main, when the declaration of referrer
is instantiated (which happens when that class is derived from, which will implicitly instantiate that class from the template).
Having some test program (instead of the register function, a function do_it is called):
struct foo : automatic_register<foo> {
static void do_it() {
std::cout << " doit ";
}
};
int main() {
std::cout << " main ";
}
Yields this output (as expected):
doit main
automatic registration of object creator function with a macro
I find your concept pretty complicated and I'm not sure if it's required. From my point of view your problem can be circumvented when adding the following code:
#include <iostream>
#include <map>
#include <string>
struct Object{}; // Value Object
// provide a simple create function to derived classes
template<class T> struct ObjectT : public Object {
static Object* create() { return new T(); }
};
struct ObjectFactory {
std::map<std::string, Object* (*)()> creators_factory;
static ObjectFactory* instance()
{
static ObjectFactory* __self = NULL;
if (__self == NULL)
__self = new ObjectFactory();
return __self;
}
template <class T> bool reg(const std::string& id, Object* (*creator)() )
{
creators_factory[id] = creator;
return true;
}
// pass in creator function pointer to register it to id
static Object* create(const std::string& id) {
return instance()->creators_factory[id]();
}
};
#define REGISTER_CHAIN(T) bool isRegistered_##T = ObjectFactory::instance()->reg<T>(#T, T::create)
struct DerivedA : public ObjectT<DerivedA> { DerivedA() { std::cout << "DerivedA constructor\n"; } };
REGISTER_CHAIN(DerivedA);
struct DerivedB : public ObjectT<DerivedB> { DerivedB() { std::cout << "DerivedB constructor\n"; } };
REGISTER_CHAIN(DerivedB);
struct DerivedC : public ObjectT<DerivedC> { DerivedC() { std::cout << "DerivedC constructor\n"; } };
REGISTER_CHAIN(DerivedC);
struct DerivedD : public ObjectT<DerivedD> { DerivedD() { std::cout << "DerivedD constructor\n"; } };
REGISTER_CHAIN(DerivedD);
int main(void)
{
// Call last link in the register chain to register all object creators
//ObjectFactory::Register<LAST_CHAIN_LINK>::chain();
delete ObjectFactory::create("DerivedA");
delete ObjectFactory::create("DerivedB");
delete ObjectFactory::create("DerivedC");
delete ObjectFactory::create("DerivedD");
return 0;
}
I hope this helps.
Best regards,
Martin
Any way to trigger creation of a list of all classes in a hierarchy in Swift 4?
I'm answering my own question; maybe it'll help someone else.
My goal is to auto initialize subclasses such that they can register with a central authority and allow the application to retrieve a list of all such classes. As I put in my edited question, above, there doesn't appear to be a way to do this in Swift. I have confirmed this now.
I've tried a bunch of different techniques and nothing seems to work. My goal was to be able to add a .swift file with a class in it and rebuild, and have everything automagically know about the new class. I will be doing this a little differently, though.
I now plan to put all subclasses that need to be initialized this way into a particular directory in my application bundle, then my AppDelegate (or similar class) will be responsible for invoking a method that scans the directory using the filenames as the class names, and instantiating each one, thus building the list of "registered" subclasses.
When I have this working, I'll come back and post the code here (or in a GitHub project and link to it).
Related Topics
Linking to Msvc Dll from Mingw
Compiling with -Static-Libgcc -Static-Libstdc++ Still Results in Dynamic Dependency on Libc.So
Does "Std::Size_T" Make Sense in C++
Are There Any Tricks to Use Std::Cin to Initialize a Const Variable
How to Initialize 3D Array in C++
How to Create My Own Ostream/Streambuf
Initializing a Union with a Non-Trivial Constructor
The Implementation of Std::Forward
What Is Wrong with Using Inline Functions
Why Can't "Transform(S.Begin(),S.End(),S.Begin(),Tolower)" Be Complied Successfully
Why Does Clang Optimize Away X * 1.0 But Not X + 0.0
Templated Class Specialization Where Template Argument Is a Template
Why Does This Program Crash: Passing of Std::String Between Dlls