Использование статической инициализации для регистрации классов

0

Поэтому я прочитал эту статью об использовании статической инициализации для регистрации классов (http://quantumgraphics.blogspot.nl/2014/11/abusing-static-initialization.html). Это именно то, что мне нужно, поэтому я решил его реализовать. Я не мог заставить его работать, поэтому я сделал небольшой тестовый пример, чтобы убедиться, что я правильно понял детали. Оказывается, даже простой пример не работает (http://ideone.com/HDr8ZM):

#include <iostream>

int a = 0;

template<
    class T
>
class Scriptable {
protected:
    struct Proxy
    {
        Proxy() {
            std::cout << "Proxy was executed! ID: " << T::id << std::endl;
            a++;
        }
    };
    static Proxy proxy_;
} ;

template<
    class T
>
typename Scriptable<T>::Proxy Scriptable<T>::proxy_;

class Object : public Scriptable<Object> {
public:
    constexpr static auto id = "[Object]";
} ;

int main() {
    std::cout << "Done " << a << std::endl;
}

Поэтому в основном то, что должно произойти (точнее, то, что я хочу сказать), заключается в том, что конструктор Proxy должен быть выполнен до main. Я хочу использовать конструктор Proxy для регистрации класса с некоторой базой базового класса singleton, но я не думаю, что связанный с этим код не работает.

Может ли кто-нибудь указать мне в правильном направлении? Мне, вероятно, не хватает флага компилятора или что-то (пример должен компилироваться только с флагом -std = С++ 11). Или, может быть, лучший способ сделать то, что я здесь пытаюсь?

Любая помощь очень ценится!

  • 0
    Это недостающий кусок головоломки. Спасибо!
Теги:
c++11

2 ответа

2
Лучший ответ

С ссылкой Pradhan я смог приготовить то, что мне нужно:

#include <iostream>

int a = 0;

template <typename T, T /*unnamed*/>
struct nnb_ForceInit { };

template<
    class T
>
class Scriptable {
public:
    struct nnb_Proxy {
        nnb_Proxy() {
            std::cout << "Proxy was executed! ID: " << T::id << std::endl;
            a++;
        }
    };

    static nnb_Proxy __nnb_proxy__;
    typedef nnb_ForceInit<nnb_Proxy&, __nnb_proxy__> __nnb_typedef_dummy__;
} ;

template<
    class T
>
typename Scriptable<T>::nnb_Proxy Scriptable<T>::__nnb_proxy__;

class Object : public Scriptable<Object> {
public:
    constexpr static auto id = "[Object]";
};

class Image : public Scriptable<Image> {
public:
    constexpr static auto id = "[Image]";
};

class Error : public Scriptable<Error> {
public:
    constexpr static auto id = "[Error]";
} ;

int main() {
    std::cout << "Done " << a << std::endl;
}

У меня нет четкого представления о том, как это работает, но похоже, что я делаю то, что хочу/отлично работает, поэтому я предполагаю, что это так.

  • 0
    это действительно работает, но хитрость заключается в добавлении nnb_ForceInit, иначе компилятор не инициализирует статическую переменную nnb_proxy
  • 0
    почему бы не инициализировать его?
1

Это не работает, потому что у вас нет причин для создания Proxy. В этом случае ваш main() даже не создает Object - поэтому почему был создан Proxy? Вы должны хотя бы сделать это:

int main() {
    Object o;
    std::cout << "Done " << a << std::endl;
}

Но тогда простое построение o никак не ссылается на прокси, так что по-прежнему нет причин для его построения. Вам придётся прикоснуться к нему как-то. Проще всего просто ссылаться на конструктор Scriptable:

Scriptable() {
    proxy_; // this line throws a warning, since this line does nothing,
            // so replace it with something reasonable. but this line is
            // enough to force proxy_ to be instantiated.
}

Если я добавлю эти два бита (Object o; и конструктор Scriptable), то ваш код даст:

Proxy was executed! ID: [Object]
Done 1

Другой способ - фактически объявить proxy_ внутри конструктора:

Scriptable() {
    static Proxy proxy_;
}
  • 0
    Это плохие новости - если это будет единственное решение, это означает, что статья, на которую я ссылаюсь, действительно неверна. Это не перечисляет ни одного из этих шагов. К счастью, в повторяющемся вопросе Прадхан предложил хитрость, которая заставляет proxy_ инициализироваться. Я добавлю решение в ответах. Спасибо за Ваш ответ!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню