Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Introspecting Function Templates

Boost , Chapter 1. The Type Traits Introspection Library , Chapter 1. The Type Traits Introspection Library

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Единственным вложенным элементом, который библиотека TTI не интроспектирует, являются шаблоны функций.

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

Техника интроспекции шаблонов классов в библиотеке TTI взята из реализации методики в библиотеке Boost MPL. В случае<BOOST_TTI_HAS_TEMPLATE>он непосредственно использует функциональность библиотеки Boost MPL, в то время как в случае<BOOST_TTI_HAS_TEMPLATE_CHECK_PARAMS>он воспроизводит большую часть техники в библиотеке Boost MPL. Техника напрямую зависит от того, что в C++ мы можем передать шаблон в качестве параметра другому шаблону, используя так называемый тип параметра шаблона.

Одна очевидная вещь о типе параметров шаблона шаблона заключается в том, что это шаблон класса. По каким бы то ни было историческим или техническим причинам, никто никогда не предполагал, что C++ имеет способ передачи шаблона функций непосредственно в качестве параметра шаблона, возможно, его можно назвать типом параметра «шаблона шаблона функций». Лично я думаю, что это будет хорошим дополнением к C++ и сделает возможность передачи шаблона в качестве параметра другому шаблону более ортогональной, поскольку будут поддерживаться как шаблоны классов, так и шаблоны функций. Мои усилия по обсуждению этого на основных новостных группах C++ столкнулись с аргументами как против его практического использования, так и с обоснованием того, что можно передать шаблон функции другому шаблону, вложенному в класс без шаблона, который служит типом. Но, конечно, мы можем сделать то же самое с шаблонами классов, что фактически и делает Boost MPL для передачи шаблонов в виде метаданных, но у нас все еще есть параметры шаблонов шаблонов в виде шаблонов классов.

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

Instantiating a nested function template

Однако существует альтернативный, но менее определенный способ интроспекции шаблона функций. Я постараюсь объяснить, почему этот способ в настоящее время не включен в библиотеку ТТИ, но сначала я объясню, что это такое.

Можно проверить, существует ли какая-либо конкретная инстанциациявложенного шаблона функций во время компиляции без возникновения ошибки компилятора. Хотя проверка того, существует ли какая-либо конкретная инстанциация вложенного шаблона функций во время компиляции, не доказывает, что вложенный шаблон функций сам по себе существует или не существует, поскольку сам инстанциация может быть неправильной и потерпеть неудачу, даже когда вложенный шаблон функций существует, он обеспечивает частичное, если некорректное, средство проверки.

Код для этого для шаблонов функций-членов выглядит так (подобный код также существует для шаблонов статических функций-членов):

template
  <
  class C,
  class T
  >
struct TestFunctionTemplate
  {
  typedef char Bad;
  struct Good { char x[2]; };
  template<T> struct helper;
  template<class U> static Good check(helper<&U::template SomeFuncTemplateName<int,long,double> > *);
  template<class U> static Bad check(...);
  static const bool value=sizeof(check<C>(0))==sizeof(Good);
  };

где «SomeFuncTemplateName» — название вложенного шаблона функций, за которым следуют некоторые параметры для его реализации. «Класс С» является типом ограждающего класса, а «Класс Т» является типом инстанцированного шаблона функции члена в качестве функции члена.

В качестве примера, если бы мы имели:

struct AType
  {
  template<class X,class Y,class Z> double SomeFuncTemplateName(X,Y *,Z &) { return 0.0; }
  };

Затем инстанцирует вышеупомянутый шаблон с:

TestFunctionTemplate
  <
  AType,
  double (AType::*)(int,long *,double &)
  >

Это дало бы нам значение Boolean, которое указывало бы, существует ли шаблон вложенных функций для конкретной инстанциации, представленной выше. Кроме того, с помощью макроса библиотека TTI может предоставить средства для указания названия вложенного шаблона функций-членов («SomeFuncTemplateName» выше) и его набора мгновенных параметров («int,long,double» выше) для генерации шаблона.

Так почему же библиотека TTI не предоставляет, по крайней мере, такой большой функционал для интроспекции шаблонов функций-членов, даже если она представляет собой частично ошибочный способ сделать это?

Причина ошеломляюще разочаровывает. Хотя вышеупомянутый код является совершенно правильным кодом C++ («кланг» работает правильно), два основных компилятора C++ во всех своих различных выпусках не могут правильно обрабатывать вышеупомянутый код. Как gcc (g++), так и Visual C++ неправильно выбирают неправильную функцию «проверки», даже когда применяется правильная функция «проверки» (Comeau C++ также терпит неудачу, но меня меньше беспокоит этот компилятор, поскольку он не используется почти так же, как два других). Все мои попытки найти альтернативу вышеупомянутому коду также провалились. Проблемы с обоими компиляторами в этом отношении легче увидеть с помощью этого фрагмента:

struct AType
 {
 template<class AA> void SomeFuncTemplate() { }
 };
template<class T>
struct Test
 {
 template<T> struct helper;
 template<class U> static void check(helper<&U::template SomeFuncTemplate<int> > *) { }
 };
int main()
  {
  Test< void (AType::*)() >::check<AType>(0);
  return 0;
  }

Оба компилятора сообщают об ошибках компиляции с этим совершенно правильным кодом.

gcc:

error: no matching function for call to 'Test<void (AType::*)()>::check(int)'

и msvc:

error C2770: invalid explicit template argument(s) for 'void Test<T>::check(Test<T>::helper<&U::SomeFuncTemplate<int>> *)'

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

template<class U> static void check(helper<&U::template SomeFuncTemplate<int> > *) { }

заменяется:

template<class U> static void check(helper<&AType::template SomeFuncTemplate<int> > *) { }

GCC и Visual C++ работают корректно. То же самое касается линии «проверить» в шаблоне «TestFunction» выше.

Но обходной путь разрушает один из основных принципов библиотеки TTI, который заключается в том, что класс, содержащийся в приложении, должен быть передан в качестве параметра шаблона, тем более что класс, содержащийся в нем, на самом деле не должен существовать (см.<BOOST_TTI_MEMBER_TYPE>и предыдущее обсуждение «Необходимых типов»), не создавая ошибки компилятора. Поэтому я решил не внедрять даже эту методологию, чтобы интроспектировать вложенные шаблоны функций в библиотеке TTI.


PrevUpHomeNext

Статья Introspecting Function Templates раздела Chapter 1. The Type Traits Introspection Library Chapter 1. The Type Traits Introspection Library может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Chapter 1. The Type Traits Introspection Library ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-07-04 21:11:58/0.0074260234832764/0