Шаблонное обходное решение typedef, похоже, не работает
Я использую C++03 (CUDA nvcc действительно, но это не имеет значения). У меня есть следующий бит рабочего кода:
template<typename T> void baz(T*);
template<typename T>
void bar() {
typedef void (*foo_t)(T*);
static const foo_t dummy = baz;
// use dummy
};
Теперь я хочу переместить фиктивную переменную из функции, сделав ее глобальной.
Первая попытка:
template<typename T> void baz(T*);
template<typename T> typedef void (*foo_t)(T*);
template<typename T> const foo_t dummy = baz;
template<typename T>
void bar() {
// use dummy
};
Это не работает, так как C++ (по крайней мере, C++03) не имеет шаблонного typedef:
error: "typedef" may not be specified here
error: "foo_t" is not a function or static data member
Почему в C++ 03 этого нет? Бьет меня Если я могу сделать это в функции, я не могу понять, почему я не смогу сделать это и снаружи. Я думаю, что C++11 тоже нет (но есть шаблонные using
, право?)
Итак, я прочитал Template typedefs - как вы работаете? и пошел за принятым ответом - используя вспомогательный класс.
Вторая попытка:
template<typename T> void baz(T*);
template<typename T> class TemplatingHeler {
typedef void (*foo_t)(T*);
static const foo_t dummy = baz;
}
... это получает:
error: a member of type "void (*const)(T *)" cannot have an in-class initializer
Третья попытка:
template<typename T> void baz(T*);
template<typename T> class TemplatingHelper {
typedef void (*foo_t)(T*);
static foo_t dummy;
};
template<typename T> TemplatingHelper::dummy = baz;
error: name followed by "::" must be a class or namespace name
error: argument list for class template "TemplatingHelper" is missing
... и nvcc segfaults (!)
Почему все это происходит, и как я могу заставить его работать?
1 ответ
Ваша третья попытка должна сработать, после исправления ошибок;)
template<typename T> void baz(T*);
template<typename T> class TemplatingHelper {
typedef void (*foo_t)(T*);
static foo_t dummy;
};
template<typename T> // template-declaration
typename TemplatingHelper<T>::foo_t // type
TemplatingHelper<T>::dummy // name
= baz; // initializer
Я согласен, что это излишне, но следует общей форме декларации:
type name initializer ;
даже если имя уже объявлено и ему присвоен тип внутри шаблона класса.
В данном случае это объявление шаблона, поэтому нам нужно добавить template<typename T>
часть; это необходимо, так как мы могли бы также обратиться к частичной специализации:
template<typename T, typename U> class TemplatingHelper<T(*)(U)>
{
typedef T(*foo_t)(U);
static foo_t dummy;
};
template<typename T, typename U>
typename TemplatingHelper<T(*)(U)>::foo_t
TemplatingHelper<T(*)(U)>::dummy
= baz;
Поскольку тип является обязательным и предшествует объявленному имени, нам нужно явно указать область, где его найти:
TemplatingHelper<T>::foo_t
К сожалению, поиск имени требует поставить typename
до этого квалифицированного имени. См. Где и почему я должен поставить ключевые слова "template" и "typename"?