Визуал С 2005 и GCC 3.4.5 компилят. IAR — нет:
Error[Pe304]: no instance of function "funcA" matches the argument list
argument types are: (int *)
detected during instantiation of "void funcT(T &) [with T=int]"
error: no instance of function "funcA" matches the argument
Лень рыться в стандарте, но вот что дает поиск:
<quote>
[temp.dep.candidate] 14.6.4.2 Candidate functions
1 For a function call that depends on a template parameter, if the function
name is an unqualified-id but not a template-id, the candidate functions
are found using the usual lookup rules (3.4.1, 3.4.2) except that:
— For the part of the lookup using unqualified name lookup (3.4.1), only
function declarations with external linkage from the template definition
context are found.
— For the part of the lookup using associated namespaces (3.4.2), only
function declarations with external linkage found in either the template
definition context or the template instantiation context are found.
</quote>
"Static functions" have internal, not external linkage, and the function
call depends on template parameter A, so it is an error.
HTH,
--
Michiel Salters
Если добавить явную квалификацию (::funcA(t), то comeau компилит:
Этот код компилится не должен.
Дело в том, что выражение funcA(&t); является зависимым, и поэтому для поиска имен используются специальные правила, а именно:
14.6.4.2/1 For a function call that depends on a template parameter, if the function name is an unqualified-id but not a
template-id, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:
— For the part of the lookup using unqualified name lookup (3.4.1), only function declarations with external
linkage from the template definition context are found.
Поскольку funcA имеет внутреннее связывание, то она как раз подпадает под преведенное выше ограничение, и поэтому не может быть найдена.
Возможно несколько решений проблемы:
1. Убрать static из объявления funcA:
void funcA(void *p) {}
2.Если вариант 1 не устраивает (имя должно быть видимо только в одной еденице трансляции), то поместить funcA в безымянное пространство имен:
Здравствуйте, fGordon, Вы писали:
G>простите за ламмерский вопрос, а разве не надо указать тип?
G>void test() G>{ G> int t; G> funcT<int>(t); G>}
Не обязательно. Вроде по 14.7.2
A trailing template-argument can be left unspecified in an explicit instantiation of a function template specialization or of a member function template specialization provided it can be deduced from the type of a function parameter (14.8.2).
Здравствуйте, fGordon, Вы писали:
НЕ>>void test() НЕ>>{ НЕ>> int t; НЕ>> funcT(t); НЕ>>}
G>простите за ламмерский вопрос, а разве не надо указать тип?
G>void test() G>{ G> int t; G> funcT<int>(t); G>}
В случае шаблонов функций компилятор в ряде случаев может самостоятельно вывести параметры шаблона.
А как это должно, по идее, работать?
funcT инстанциируется где попало, из каждой единицы трансляции зовёттся своя funcA... ЧТо-то тут не того...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Непомнящий Евгений, Вы писали:
E>А как это должно, по идее, работать? E>funcT инстанциируется где попало, из каждой единицы трансляции зовёттся своя funcA... ЧТо-то тут не того...
Это все сделано локально в одном cpp файле и наружу не торчит. Собственно поэтому и объявил funcA как static.
Возможно, кстати и funcT следовало сделать static...
Здравствуйте, Непомнящий Евгений, Вы писали:
НЕ>Это все сделано локально в одном cpp файле и наружу не торчит. Собственно поэтому и объявил funcA как static. НЕ>Возможно, кстати и funcT следовало сделать static...
а шаблоны так вроде бы не умеют... В смысле "не торчать наружу"
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Bell, Вы писали:
B>Она и без static не будет доступна, если определена в .cpp файле. B>Компилятору при испольщовании шаблона требуется его полное определение.
А если я в a.cpp и в b.cpp определю шаблон функции c одним именем и разными телами:
у меня разве не будет ошибки линковки? Компилер же создает на основании шаблона функции имя функции для линкера — вроде как добавляя к имени шаблона имена типов с которыми его инстанцировали. Получится, что у меня две разные функции с одинаковым декорированным именем...
Здравствуйте, Непомнящий Евгений, Вы писали:
НЕ>у меня разве не будет ошибки линковки? Компилер же создает на основании шаблона функции имя функции для линкера — вроде как добавляя к имени шаблона имена типов с которыми его инстанцировали. Получится, что у меня две разные функции с одинаковым декорированным именем...
Ошибки линковки может и не быть, но нарушение ODR точно будет
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
НЕ>у меня разве не будет ошибки линковки?
В случае с шаблонами ошибки линковки не будет, а вот нарушение ODR (и соответственно неопределенное поведение) — будет.
Подробности в 3.2.
Здравствуйте, Непомнящий Евгений, Вы писали:
НЕ>Это все сделано локально в одном cpp файле и наружу не торчит. Собственно поэтому и объявил funcA как static. НЕ>Возможно, кстати и funcT следовало сделать static...
static-функции (в прочем как и переменные) в текущем стандарте поминаются как deprecated (7.3.1.1/2).
Используй безымянные пространства имен, и будет тебе счастье: