Оглавление

Регистрация шаблона

Шаблоны AngelScript очень похожи на шаблоны C++. Реализация шаблона однако не похожа на C++-реализацию, так как шаблон должен быть реализован в виде общего класса, который может определять динамические действия во время выполнения на основе подтипа, для которого он использовался. Это, безусловно, гораздо менее эффективно, чем наличие конкретных реализаций для каждого типа, поэтому AngelScript разрешает регистрировать шаблонную специализацию там, где требуется дополнительная производительность.

Таким образом мы убиваем двух зайцев, имея высокую производительно там где подтип известен, и поддержку всех других типов, о которых мы не знаем заранее.

Регистрация

Регистрация шаблонов похожа на обычную регистрацию ссылки, с небольшими отличиями. Имя типа складывается из имени шаблонного типа плюс имя подтипа в угловых скобках, так же необходимо указыват OBJ_TEMPLATE.
// Регистрация шаболна
r = engine->RegisterObjectType("myTemplate", 0, asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); assert( r >= 0 );

Шаблонный тип по умолчанию не использует сборщика мусора, но если вы не знаете сколько обьектов породит шаблон, рекомендуется его подключить

Когда регистрируем отношения, методы и свойства для шаблонного типа, имя шаблонного типа состоит из имени шаблона и типа в угловых скобках, без слова class (myTemplate < Type >). Имя типа должно совпадать с именем, обьявленным с помошью RegisterObjectType.

Отношения для шаблонов так же отличаются от обычной регистрации отношени. Для получения созданног типа фабрика получает asIObjectType первым скрытым параметром. При регистрации фабрики этот скрытый параметр отражен в декларации (int &in).

// Регистрация отношений
r = engine->RegisterObjectBehaviour("myTemplate", asBEHAVE_FACTORY, "myTemplate@ f(int&in)", asFUNCTIONPR(myTemplateFactory, (asIObjectType*), myTemplate*), asCALL_CDECL); assert( r >= 0 );

Списочная фабрика регистрируется аналогично :

// Регистрация отношений списочной фабрики
r = engine->RegisterObjectBehaviour("myTemplate", asBEHAVE_LIST_FACTORY, "myTemplate@ f(int&in, uint)", asFUNCTIONPR(myTemplateListFactory, (asIObjectType*, unsigned int), myTemplate*), asCALL_CDECL); assert( r >= 0 );

Помните, так как тип определяется в рантайме, не возможно обьявить функции для получения типа по значению, поэтому необходимо использовать ссылки. Как вариант - использовать хендлы, но тогда скриптовый движок не сможет использовать шаблон для типов-значений.

Еще:
Шаблон массива

Проверка экземпляров шаблона во время компиляции

Для избежания ненужных проверок экземпляров шаблона во время исполнения, можно зарегестрировать asBEHAVE_TEMPLATE_CALLBACK. Это специальная функция, которую вызывает скриптовый движок каждый раз, когда генерируется новый шаблон. Каллбек выполняет необходимые проверки, чтобы убедиться что тип может быть обработан, и в противном случае сообщить об ошибке.

Каллбек должен быть глобальной функцией, которая принимает указатель на asIObjectType, и возвращает true в случае успеха.

// Регистрируем каллбек
r = engine->RegisterObjectBehaviour("myTemplate", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int &in)", asFUNCTION(myTemplateCallback), asCALL_CDECL); assert( r >= 0 );

Вот функция каллбека:

bool myTemplateCallback(asIObjectType *ot)
{
  // Этот шаблон поддерживает только примитивные типы
  int typeId = ot->GetSubTypeId();
  if( typeId & asTYPEID_MASK_OBJECT )
  {
    // Скрипт пытается создать экземляр шаблона с типом обьекта, это не допускается
    return false;
  }
    
  // Примитивные типы разрешены
  return true;
}

Специализация

При регистрации специализации шаблона вы можете перегрузить шаблон, чтобы AngelScript мог скомпилировать декларацию с определенным типом. Это позволяет приложению регистрировать разные обьекты с их собственной реализацией шаблонной специализации. Тут легко запутаться, поэтому используйте разные названия методов и отношений для шаблонного типа и шаблонной специализации.

Специализации шаблонов регистрируется следующим образом :

// Регистрируем специализацию для типа float
r = engine->RegisterObjectType("myTemplate", 0, asOBJ_REF); assert( r >= 0 );
  
// Регистрируем фабрику (нет скрытых параметров для специализации)
r = engine->RegisterObjectBehaviour("myTemplate", asBEHAVE_FACTORY, "myTemplate@ f()", asFUNCTION(myTemplateFloatFactory, (), myTemplateFloat*), asCALL_CDECL); assert( r >= 0 );

Текущие ограничения


Перевод - arroy.one@gmail.com. При копировании материалов указывайте ссылку на источник.