Ошибка компоновки встроенной функции, объявленной в hpp, реализованной в cpp и использованной в другой cpp - PullRequest
0 голосов
/ 25 марта 2020

Я получаю ошибки компоновщика undefined reference to function, когда пытаюсь скомпилировать следующий проект:

header.hpp

inline void f(double*, double*, double*);

impl. cpp

inline void f(double* A, double* B, double* C){ ... }

use. cpp

#include "header.hpp"

int main(){
    double *A, *B, *C;
    f(A, B, C);
    return 0;
}

Я компилирую с g++ -std=c++11 header.hpp impl.cpp use.cpp. Затем компоновщик говорит undefined reference to f в файле use.cpp.

Я заметил, что если я удалю ключевое слово inline, все будет работать нормально, но я бы хотел сохранить его.

Кроме того, Я заметил, что если в use.cpp вместо этого включить impl.cpp, все также работает нормально, но, опять же, это не то, что я хочу делать, так как я хочу создать несколько двоичных файлов с использованием файлов impl.cpp, impl2.cpp и т. Д. и, следовательно, жесткое кодирование одного из них также не подходит.

Есть ли способ, как сделать такой проект компиляцией и связью?

Ответы [ 2 ]

4 голосов
/ 25 марта 2020

Спецификатор inline не должен сообщать компилятору, что он должен встроить эту функцию во время оптимизации. Это было долгое время go, но между тем было понято, что компиляторы намного лучше принимают это решение:

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

Поскольку это значение ключевого слова inline не является обязательным, компиляторы могут использовать встроенную подстановку для любой функции, которая не помечена как inline, и могут генерировать вызовы функций для любой функции, помеченной как inline. Эти варианты оптимизации не изменяют правила, касающиеся нескольких определений и общей статики, перечисленных выше.

Вам нужно inline, когда вы хотите определить встроенную функцию;). В вашем примере inline позволит вам иметь в заголовке

inline void f(double*, double*, double*) {}

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

код предназначен для сравнения и я хотел предотвратить накладные расходы на вызов функции

Если удаление накладных расходов на вызов функции является жизнеспособной оптимизацией, компилятор поймет это и будет действовать соответственно.

0 голосов
/ 25 марта 2020

Определение встроенной функции или переменной (начиная с C ++ 17) должно быть доступно в единице перевода, к которой к ней осуществляется доступ (необязательно до точки доступа).

source: https://en.cppreference.com/w/cpp/language/inline

use.cpp не имеет доступа для определения f, поэтому вы получаете ошибку компоновщика.

Почему вы хотите f быть встроенным?

...