В зависимости от того, что именно и в каком порядке мы напишем в main, получим разные результаты — включая ошибку линковки!
В чём тут проблема: определение foo<Ptr> видит только объявления foo<class> и само себя, естественно, — а foo<Vec> ещё не видит.
Поэтому foo(vector<int>) оказывается неоднозначным.
С одной стороны, компилятор инстанцирует его из foo(vector<int>*) как foo<class=vector<int>>;
с другой стороны, из main и/или из foo<Vec> — как foo<Vec=vector<int>>.
Ограничения не входят в манглированное имя (мы можем объявить параметр как концепт, или можем выписать requires, — эффект будет тот же).
Поэтому компилятор не различает эти функции, и мы отхватываем нарушение ODR.
Он или берёт ранее инстанцированную функцию из своего кеша, или принудительно создаёт ещё один объект в объектном файле, удивляя линкера. А при оптимизациях, подозреваю, начнёт хаотически инлайнить / вызывать что бог на душу положит.
Как исправить программу — очевидно. Надо выписать объявления до определений. (Минимально достаточно в данном случае вытащить третье объявление перед вторым определением).
Или, как вариант, запихнуть шаблоны функций в class scope, — там правила видимости другие, все видят всех сразу.
Вопрос в другом.
ЧТО ЭТО?
— дефект стандарта
— дефект правил манглирования имён
— или тут по стандарту должно было возникнуть ODR, и спрос исключительно с клиентского кода?
Здравствуйте, Кодт, Вы писали:
К>ЧТО ЭТО? К>- дефект стандарта К>- дефект правил манглирования имён К>- или тут по стандарту должно было возникнуть ODR, и спрос исключительно с клиентского кода?
То что манглирования имён имён не имеет информации об ограничениях на функцию косяк стандарта.
Но не переживайте думаю в стандарте просто допишут что такая ситуация UB.
ps: вспомниля анекдот
Мама с Вовочкой приходит к доктору:
-Доктор, вылечите моего ребенка!
Доктор:
-Раздевайтесь.
Мать:
-Но ведь не меня лечить нужно, а ребенка!
Доктор:
-Раздевайтесь! Чем такого лечить, проще нового сделать!
Ну вот я глубоко уверен, что вся концепция концептов — это дефект стандарта.20ка вообще полна их. Модули, концепты, корутины, вот это все — типичные баги стандарта, как по мне.
проблема никуда не уходит, один к одному такая же. И тут можно явно применять следующее
12.3 Declaration matching [over.dcl]
1 Two function declarations of the same name refer to the same function if they are in the same scope and
have equivalent parameter declarations (12.2) and equivalent (13.7.6.1) trailing requires-clauses, if any (9.3).
то есть, конфликта быть не должно потому что разные trailing requires-clauses. Думаю, что в случае концептов в заголовке шаблона — ситуация должна разруливаться точно так же. Наверное в последних редакциях стандартах уже так и написано, но лень искать.. К>- дефект правил манглирования имён
Однозначно да. Ограничения должны входить в имя, но не входят.
[добавлено позже] .. потому что манглированное имя производится из сигнатуры, а она определяется так
К>ЧТО ЭТО? К>- дефект стандарта К>- дефект правил манглирования имён К>- или тут по стандарту должно было возникнуть ODR, и спрос исключительно с клиентского кода? Возможно, второе.
Здравствуйте, Кодт, Вы писали:
К>В зависимости от того, что именно и в каком порядке мы напишем в main, получим разные результаты — включая ошибку линковки!
В принципе, это очень похоже на баг, который существовал когда-то в Visual C++ 6.0: параметр шаблона функции, не фигурирующий в типах формальных параметров, не участвовал в декорировании имен. И так же точно такая функция инстанцировалась только один раз с тем типом, с которым впервые использовалась. Я думаю, многие помнят еще, как приходилось добавлять фейковые параметры функций, чтобы обойти эту проблему.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, vopl, Вы писали:
К>>- дефект правил манглирования имён V>Однозначно да. Ограничения должны входить в имя, но не входят.
V>[добавлено позже] .. потому что манглированное имя производится из сигнатуры, а она определяется так V>
Вот оно!
Сдаётся мне, и gcc и clang одинаково облажались, потому что этот пункт был дописан уже после того, как они внедрили концепты-ограничения как экспериментальную фичу.
Ну а дальше вся разница в их поведении связана с тем, что оно из-за этого бага неопределённое.