Итог:
Если gtest используется только в моем cpp-файле, все работает. Если gtest используется в нескольких файлах, то переопределение моей функции необходимо включить во все эти файлы! Если хотя бы в одном из этих файлов моя функция не определена, то она перестает вызываться (в моем cpp) и вместо нее используется шаблон.
Более того, даже если я убираю inline (и тогда использую функцию только в своем cpp-файле), все остается по-прежнему. Используется шаблон, а не моя свободная ф-ция. Какого х? Куда смотрит линкер?? Я так понимаю, по шаблону генерируются сигнатура, которая полностью совпадает с моей свободной функцией.
Два вопроса:
1. Почему это глотает линкер?
2. Как сделать так, чтобы гарантированно вызывалась моя функция? (не запихивая хидер с нею во все cpp-шники)
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
B>Два вопроса: B>1. Почему это глотает линкер?
таковы правила, обычная и шаблонная функция для линкера выглядят разными
B>2. Как сделать так, чтобы гарантированно вызывалась моя функция? (не запихивая хидер с нею во все cpp-шники)
надо запихать, таковы правила игры
Здравствуйте, K13, Вы писали:
B>>Куда смотрит линкер?? Я так понимаю, по шаблону генерируются сигнатура, которая полностью совпадает с моей свободной функцией.
K13>Неа. K13>если нет явной функции, вызывается PrintTo<MyType>(), сигнатура которой никак не совпадает с обычной функцией PrintTo()
Хорошо. Почему тогда в моем cpp-файле, где объявлена свободная функция, она игнорируется и используется шаблонная?
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
B>>Два вопроса: B>>1. Почему это глотает линкер? U>таковы правила, обычная и шаблонная функция для линкера выглядят разными
Ок.
B>>2. Как сделать так, чтобы гарантированно вызывалась моя функция? (не запихивая хидер с нею во все cpp-шники) U>надо запихать, таковы правила игры
Хорошо. Почему тогда в моем cpp-файле, где объявлена свободная функция, она игнорируется и используется шаблонная?
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Basil2, Вы писали:
B>>Хорошо. Почему тогда в моем cpp-файле, где объявлена свободная функция, она игнорируется и используется шаблонная?
К>Если у тебя аргумент — не MyType, а какой-нибудь MyDerivedType или MyType volatile, то шаблонная лучше подходит. К>http://liveworkspace.org/code/2EpCyA$1
Согласен (кстати, не знал насчет volatile). Но у меня именно MyType.
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, Basil2, Вы писали:
B>[ccode]template <typename T> B>Более того, даже если я убираю inline (и тогда использую функцию только в своем cpp-файле), все остается по-прежнему. Используется шаблон, а не моя свободная ф-ция. Какого х? Куда смотрит линкер??
Компилер смотрит на объявления функций выши точки вызова и видит только шаблонное объявление.
B>Два вопроса: B>1. Почему это глотает линкер? B>2. Как сделать так, чтобы гарантированно вызывалась моя функция? (не запихивая хидер с нею во все cpp-шники)
Ну наверно объявить свободную функцию до вызова?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, ononim, Вы писали:
B>>2. Как сделать так, чтобы гарантированно вызывалась моя функция? (не запихивая хидер с нею во все cpp-шники) O>как-нибудь так: O>
Здравствуйте, Vain, Вы писали:
V>Компилер смотрит на объявления функций выши точки вызова и видит только шаблонное объявление.
B>>2. Как сделать так, чтобы гарантированно вызывалась моя функция? (не запихивая хидер с нею во все cpp-шники) V>Ну наверно объявить свободную функцию до вызова?
В том то и дело, что в моем файле я объявляю _до_ вызова. И это работает.
Но если в других файлах есть подобный вызов, то используется шаблон. Т.е. это разные единицы трансляции и, как я понимаю, в дело вступает линкер. И вот тут я понять его не могу.
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, Basil2, Вы писали:
V>>Компилер смотрит на объявления функций выши точки вызова и видит только шаблонное объявление. B>>>2. Как сделать так, чтобы гарантированно вызывалась моя функция? (не запихивая хидер с нею во все cpp-шники) V>>Ну наверно объявить свободную функцию до вызова? B>В том то и дело, что в моем файле я объявляю _до_ вызова. И это работает. B>Но если в других файлах есть подобный вызов, то используется шаблон.
А объявление где, до или после? И как я понимаю, ты уже сделал дамп препроцессора на таких файлах и убидился в этом?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, wander, Вы писали:
B>>1. Почему это глотает линкер? W>Надо понять одну вещь: линкер тут не при чем.
Окей, разъясни тогда плз почему.
Если работа кода меняется при изменении в другой единицы трансляции, то кто за это отвечает?
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, Vain, Вы писали:
V>>>Компилер смотрит на объявления функций выши точки вызова и видит только шаблонное объявление. B>>>>2. Как сделать так, чтобы гарантированно вызывалась моя функция? (не запихивая хидер с нею во все cpp-шники) V>>>Ну наверно объявить свободную функцию до вызова? B>>В том то и дело, что в моем файле я объявляю _до_ вызова. И это работает. B>>Но если в других файлах есть подобный вызов, то используется шаблон. V>А объявление где, до или после? И как я понимаю, ты уже сделал дамп препроцессора на таких файлах и убидился в этом?
Объявление чего?
В моем cpp-файле, свою свободную функцию я объявляю до.
В других единицах трансляции я эту функцию либо не объявляю вовсе (тогда в моем файле перестает вызываться свободная), либо везде объявляю тоже до, и тогда все работает.
При этом я хочу, чтобы вызов свободной функции работал независимо от других единиц трансляции, что не требовалось подключать хидер с моей функцией во все существующие cpp-файлы. Не так уж многого ведь хочу?
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, Basil2, Вы писали:
B>Здравствуйте, uzhas, Вы писали:
B>>>2. Как сделать так, чтобы гарантированно вызывалась моя функция? (не запихивая хидер с нею во все cpp-шники) U>>надо запихать, таковы правила игры B>Хорошо. Почему тогда в моем cpp-файле, где объявлена свободная функция, она игнорируется и используется шаблонная?
Не копался во внутренностях gtest, но, судя по всему, обычное нарушение ODR.
Таким образом, в разных единицах трансляции получаем разные определения gtest_assert<MyType>, если она заинлайнится, то в 1.cpp будет вызов print<T>, в 2.cpp — print(MyType), иначе, будет зависеть от того, какой вариант gtest_assert выберет линковщик. Кроме того, не забываем, что это вообще-то UB.
Здравствуйте, k.o., Вы писали:
KO>Таким образом, в разных единицах трансляции получаем разные определения gtest_assert<MyType>, если она заинлайнится, то в 1.cpp будет вызов print<T>, в 2.cpp — print(MyType), иначе, будет зависеть от того, какой вариант gtest_assert выберет линковщик.
Спасибо. Пожалуй что так и есть. То есть единственный вариант это включать везде?
KO>Кроме того, не забываем, что это вообще-то UB.
А не круто ли? Вроде ничего такого не делали, а тут сразу UB Хотя, ведь C++ же...
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, Basil2, Вы писали:
B>Здравствуйте, k.o., Вы писали:
KO>>Таким образом, в разных единицах трансляции получаем разные определения gtest_assert<MyType>, если она заинлайнится, то в 1.cpp будет вызов print<T>, в 2.cpp — print(MyType), иначе, будет зависеть от того, какой вариант gtest_assert выберет линковщик. B>Спасибо. Пожалуй что так и есть. То есть единственный вариант это включать везде?
В общем да. Можно вместо PrintTo переопределить operator<<, с одной стороны, никакой разницы нет, но, в отличие от PrintTo, operator<< не специфичен для gtest и его вполне можно декларировать в одном файле с MyType. Еще как вариант, поменять gtest, чтобы требовалась явная реализация всех таких операций.
KO>>Кроме того, не забываем, что это вообще-то UB. B>А не круто ли? Вроде ничего такого не делали, а тут сразу UB Хотя, ведь C++ же...
Здравствуйте, Basil2, Вы писали:
V>>А объявление где, до или после? И как я понимаю, ты уже сделал дамп препроцессора на таких файлах и убидился в этом? B>Объявление чего?
твоей свободной функции
B>В моем cpp-файле, свою свободную функцию я объявляю до. B>В других единицах трансляции я эту функцию либо не объявляю вовсе (тогда в моем файле перестает вызываться свободная), либо везде объявляю тоже до, и тогда все работает.
естественно
B>При этом я хочу, чтобы вызов свободной функции работал независимо от других единиц трансляции, что не требовалось подключать хидер с моей функцией во все существующие cpp-файлы. Не так уж многого ведь хочу?
Много хочешь. Выборка из набора функций проходит на этапе компиляции.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]