2012-01-20 3 views
0

У меня есть заголовок, где я поставил определение шаблона функции:шаблона ссылки ошибки

template <typename FT, typename std::enable_if< !std::is_array<FT>::value, int >::type =0 > 
int fieldRW(lua_State* l, FT* ptr, bool write){ return scalarFieldRW<FT>(l, ptr, write); } 

в .cpp блоке я получаю указатель на эту функцию шаблона, и я ожидаю, что компилятор для экземпляр шаблона:

typedef int (*_fieldRW)(lua_State*, void*, bool); 
int dummy=3; 
_fieldRW aFunctionPointer=_fieldRW(fieldRW<decltype(dummy)>); 

Все компилируется. Но я получаю следующую ошибку линковки:

/home/pisto/sorgenti/hopmodv4/src/fpsgame/server.cpp:39: undefined reference to `int fieldRW(lua_State*, int*, bool)'

Обратите внимание, что компилятор правильно выбирает шаблон, определенный в заголовке (потому что он добавляет по умолчанию второго аргумента шаблона), но, видимо, не в состоянии на самом деле создать экземпляр шаблон.

EDIT: Это выглядит определенно как ошибка. Смотрите эти тесты: http://pastebin.com/5Yjsv47H Кроме того, еще один признак того, что это, вероятно, будет ошибкой в ​​г ++ является то, что если я делаю это:

int main() { 
     int dummy=3; 
     int (*inted)(int*)=asd<decltype(dummy)>; 
     int (*voided)(void*)=(int (*)(void*))asd<decltype(dummy)>; 
     voided(&dummy); 
} 

г ++ предупреждает о неиспользуемой переменной inted но компилирует мелко.

+0

является тип парам 'FT *' должен быть 'недействительным *' или ' int * '? Кажется, что ваш код и ошибка компоновщика не согласуются. – Useless

+0

Я ожидаю, что последняя строка второго фрагмента кода создаст функцию fieldRW с FT = int. Не имеет значения, если тогда я передам функцию другому типу функции, это только для полноты моего примера. –

+0

Ну ладно, кастинг на другой тип указателя функции (который чувствует себя как-то необычайно, что-то делать) бросил меня. У меня нет стандартной возможности проверять правила экземпляра шаблона шаблона, схожего кто-то еще делает ... – Useless

ответ

1

Ответ, вероятно, тонкость в спецификации указателя функции литья:

The standard says in [expr.reinterpret.cast] "A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling a function through a pointer to a function type (8.3.5) that is not the same as the type used in the definition of the function is undefined."

So I think the program has undefined behaviour. Because you never call asd as part of a valid expression it doesn't need to be instantiated.

Clang++ fails in the same way as G++ 4.6, but it works with G++ 4.7

(спасибо Джонатану Wakely)

+0

Указатели функции каста очень плохие. Код никогда не должен бросать указатели на функции, кроме тех, которые возвращаются из 'dlsym' или' GetProcAddress', и даже тогда только к их истинному типу. –

+0

Я верну их обратно к настоящей подписи перед использованием. Я должен сделать это, потому что я храню указатель в списке, который содержит разнородные типы указателей на функции (а именно, все разные по типу указателей второго аргумента). –

+0

Для этого вам не нужно использовать незаконные роли. Вместо этого поместите указатели функций в структуру с общим базовым классом. –

Смежные вопросы