Каковы правила создания экземпляров типов шаблонов (класс / функция) при получении адреса? - PullRequest
6 голосов
/ 18 июля 2011

Отвечая на этот вопрос, я столкнулся с этой разницей в поведении в отношении создания шаблона.

Изначально существует шаблон функции

template <typename T> void my_callback(void* data) { … }

Теперь что-то требует адрес этого - в частности, void*, поэтому очевидный подход -

bar(reinterpret_cast<void*>(&my_callback<int>));

Однако в версиях компилятора, предшествующих gcc 4.5, это завершается ошибкой с недостаточным контекстом ... ошибка. Прекрасно - так что исправление - это сначала «сотворение», что заставляет инстанцировать, то есть:

void (*callback)(void*) = my_callback<int>;
bar(reinterpret_cast<void*>(callback));

Это отлично работает.

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

template <typename T>
struct foo
{
  static void my_callback(void* data) {
    T& x = *static_cast<T*>(data);
    std:: cout << "Call[T] with " << x << std::endl;
  }
};

Теперь оригинал reinterpret_cast работает нормально.

bar(reinterpret_cast<void*>(&foo<int>::my_callback));

Итак, мой вопрос - почему эта очевидная разница в поведении?

1 Ответ

2 голосов
/ 18 июля 2011

Начиная с n3290, 14.7.1. Неявное создание экземпляра [temp.inst]

2 Если специализация шаблона функции не была явно создана или явно специализирована, специализация шаблона функции создается неявно, когда специализацияссылка в контексте, который требует определения функции.

В параграфе 1 есть аналогичные правила для специализаций шаблонов классов.Обратите внимание, что Стандарт говорит в терминах специализации, потому что специализация неявно объявляется, когда используется шаблон, здесь нет никакой предоставленной пользователем специализации, по крайней мере, для шаблонов функций (параграф 8).

В сочетании с параграфом 10,

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

Я думаю, что практическое правило таково: как только необходим объект / член / функция класса или чтобы программа работала иначе (неформально), шаблон неявно создается, но не раньше .Это включает в себя получение адреса функции.

Что касается вопроса, который вы связали, то некоторые варианты использования reinterpret_cast могут привести к тому, что программа станет несовместимой, и к этому времени упоминания о случаях неуместны - Iприглашаю посмотреть мой ответ там <<b> / бесстыдник>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...