На моем Linux-компьютере есть 2 библиотеки:
libfoo1.a and libfoo2.a
и они оба содержат реализацию
void foo(int)
и моя основная программа вызывает foo:
int main() { foo(1); return 0; }
Я скомпилировал программу двумя способами, используя g ++
g++ main.cpp libfoo1.a libfoo2.a -o a1.out
g++ main.cpp libfoo2.a libfoo1.a -o a2.out
Когда я запускаю программы, a1 явно использует реализацию foo () из libfoo1.a, в то время как a2 явно использует libfoo2. То есть g ++ связывается с тем foo (), который он видел первым.
Мой вопрос (наконец-то) заключается в том, действительно ли эта «жадная» политика компоновки указана в стандарте C ++? Или другой компилятор / платформа будет вести себя по-разному в зависимости от реализации?
PS: Чтобы поставить вопрос в практический контекст, мне действительно нравится, как работает этот пример g ++. В моем реальном приложении у меня есть устаревшая библиотека libfoo2, которая реализует много (много!) Функций, но я хочу предоставить новые реализации для нескольких из них в libfoo1. С одной стороны, я мог бы написать совершенно новый интерфейс в libfoo1, реализовать свою кучку, а затем делегировать libfoo2 для оставшейся части. Но я бы предпочел отказаться от написания всего этого кода делегирования, если бы я мог полагаться на линкеры, чтобы сделать это для меня (даже для компиляторов не-g ++, таких как icc).
PPS: Чтобы поместить это в реальный практический контекст, libfoo2 - это blas, а libfoo1 - это доморощенная реализация OpenMP некоторых из его подпрограмм. Я не готов раскошелиться на МКЛ. ATLAS не поддерживает многопоточность функций, которые я хочу вызвать. Он очень хорош в многопоточности GEMM, но мне нужно, чтобы некоторые из более причудливых подпрограмм из LAPACK тоже были быстрыми (zsptrf / zsptrs / zspr). Похоже, что моя неосведомленная о кеше реализация OpenMP этих подпрограмм может работать лучше, чем ее последовательная реализация с настройкой кеша.
Извините за длину сообщения.