Има ли начин да се извика функция за инициализация само когато се инстанцира конкретен шаблон на клас (специализация)?

Проектирам обвивка върху различни изчислителни функции. Някои от базовите бекенди изискват извикване на някои функции за стартиране, преди да бъдат направени други извиквания на API. Мога да използвам някаква статична променлива, която е инициализирана преди main, и да я обвия в някаква функция, както е описано тук, за да мога да хвана всички грешки, възникнали по време на инициализацията.

Чудя се дали има по-добър начин да се справя с това. Имайте предвид, че никога няма да има екземпляр на шаблона на класа, тъй като всичко е или typedef, или статичен член.


person rubenvb    schedule 29.04.2015    source източник
comment
Заглавието е напълно грешно, не описва въпроса.   -  person Mykhaylo Kopytonenko    schedule 29.04.2015
comment
Защо не делегирате от статичните членове към единичен екземпляр - който ще бъде инициализиран при първото използване (и който може да обработва правилно грешки?)   -  person Nim    schedule 29.04.2015


Отговори (1)


За да реша проблема с инициализирането на API само за някои специализации и с инициализирането му само веднъж, бих направил нещо подобно:

#include <iostream>

template <typename T>
struct Wrapper
{
    // class who will be statically instantiated
    struct CtorClass
    {
        CtorClass()
        {
            std::cout << "Init\n";
        }
    };

    static CtorClass static_ctor;

    static void compute1(){}
    static void compute2(){}

};

// definition for template static member cons
template <typename T>
typename Wrapper<T>::CtorClass Wrapper<T>::static_ctor;

struct NeedInit{};

// you will have to use static_ctor in every funcition of the
template <>
void Wrapper<NeedInit>::compute1()
{
    static_ctor;
}

template <>
void Wrapper<NeedInit>::compute2()
{
    static_ctor;
}

int main()
{
    Wrapper<int>::compute1();
    Wrapper<int>::compute2();
    Wrapper<NeedInit>::compute1();
    Wrapper<NeedInit>::compute2();
}

За съжаление, по този начин трябва да използвате static_ctor във всяка функционална специализация, която принадлежи към Wrapper<NeedInit> клас. Но не е необходимо да проверявате дали инициализацията вече е извикана.

Тогава можете да уловите грешки, както казахте.

person Paolo M    schedule 29.04.2015
comment
Добре, това е един от начините, които съм измислил наполовина. Това налага наказание по време на изпълнение, макар и много по-малко наказание от потребителя да бъде принуден да извика функция за стартиране. Как std::cout се справя с това? Мислех, че има някакъв механизъм за инициализиране на stdio, когато се използва. - person rubenvb; 29.04.2015
comment
@rubenvb Ммм, не знам как мога да се справя с io инициализацията. Може би се изпълнява винаги, когато ‹iostream› е включен, дори ако cout не се използва? - person Paolo M; 30.04.2015