Size: a a a

cxx.Дискуссионная

2020 May 25

АК

Александр Караев... in cxx.Дискуссионная
Александр Караев
я не про инлайнинг, а про inline
приведи пример использования и посмотри, что при этом генерируется (тело inline конструктора, скорее всего), а потом посмотри на правила ODR
источник

O

Ofee in cxx.Дискуссионная
Александр Караев
приведи пример использования и посмотри, что при этом генерируется (тело inline конструктора, скорее всего), а потом посмотри на правила ODR
Допустим, у нас такие файлы:

$ cat foo.hpp
// Our library header
#include <string>

struct Foo {
   Foo() = default;
   std::string bar = SOME_MACRO;
   void do_magic();
};

$ cat foo.cpp
#include "foo.hpp"

#include <iostream>

void Foo::do_magic() {
   std::cout << bar << std::endl;
}

Компилируем её:
g++ foo.cpp -shared -DSOME_MACRO=\"something\" -o libfoo.so -fpic

И три разных пользователя по-разному используют библиотеку:

$ cat first.cpp
#include "foo.hpp"

int main() {
   Foo foo;
   foo.do_magic();
}

$ g++ first.cpp -o first -DSOME_MACRO=\"something\" -L. -lfoo
$ LD_LIBRARY_PATH=. ./first
something



$ g++ first.cpp -o second -DSOME_MACRO=\"something\ wrong\" -L. -lfoo
$ LD_LIBRARY_PATH=. ./second
something wrong



$ cat third.cpp
#include "foo.hpp"

int main() {
   Foo foo{"booom!"};
   foo.do_magic();
}

$ g++ third.cpp -o third -DSOME_MACRO=\"something\ wrong\" -L. -lfoo
$ LD_LIBRARY_PATH=. ./third
booom!
источник

O

Ofee in cxx.Дискуссионная
Ofee
Допустим, у нас такие файлы:

$ cat foo.hpp
// Our library header
#include <string>

struct Foo {
   Foo() = default;
   std::string bar = SOME_MACRO;
   void do_magic();
};

$ cat foo.cpp
#include "foo.hpp"

#include <iostream>

void Foo::do_magic() {
   std::cout << bar << std::endl;
}

Компилируем её:
g++ foo.cpp -shared -DSOME_MACRO=\"something\" -o libfoo.so -fpic

И три разных пользователя по-разному используют библиотеку:

$ cat first.cpp
#include "foo.hpp"

int main() {
   Foo foo;
   foo.do_magic();
}

$ g++ first.cpp -o first -DSOME_MACRO=\"something\" -L. -lfoo
$ LD_LIBRARY_PATH=. ./first
something



$ g++ first.cpp -o second -DSOME_MACRO=\"something\ wrong\" -L. -lfoo
$ LD_LIBRARY_PATH=. ./second
something wrong



$ cat third.cpp
#include "foo.hpp"

int main() {
   Foo foo{"booom!"};
   foo.do_magic();
}

$ g++ third.cpp -o third -DSOME_MACRO=\"something\ wrong\" -L. -lfoo
$ LD_LIBRARY_PATH=. ./third
booom!
Оторван ли ноги у двух последних пользователей нашей замечательной библиотеки?
источник

АК

Александр Караев... in cxx.Дискуссионная
Ofee
Допустим, у нас такие файлы:

$ cat foo.hpp
// Our library header
#include <string>

struct Foo {
   Foo() = default;
   std::string bar = SOME_MACRO;
   void do_magic();
};

$ cat foo.cpp
#include "foo.hpp"

#include <iostream>

void Foo::do_magic() {
   std::cout << bar << std::endl;
}

Компилируем её:
g++ foo.cpp -shared -DSOME_MACRO=\"something\" -o libfoo.so -fpic

И три разных пользователя по-разному используют библиотеку:

$ cat first.cpp
#include "foo.hpp"

int main() {
   Foo foo;
   foo.do_magic();
}

$ g++ first.cpp -o first -DSOME_MACRO=\"something\" -L. -lfoo
$ LD_LIBRARY_PATH=. ./first
something



$ g++ first.cpp -o second -DSOME_MACRO=\"something\ wrong\" -L. -lfoo
$ LD_LIBRARY_PATH=. ./second
something wrong



$ cat third.cpp
#include "foo.hpp"

int main() {
   Foo foo{"booom!"};
   foo.do_magic();
}

$ g++ third.cpp -o third -DSOME_MACRO=\"something\ wrong\" -L. -lfoo
$ LD_LIBRARY_PATH=. ./third
booom!
многабукаф
источник

O

Ofee in cxx.Дискуссионная
Короче, конструктор = default;, а компилируем юзер-код с максимально разными вариациями предефайн макроса и наличием/отсутствием агрегатной инициализации
источник

O

Ofee in cxx.Дискуссионная
Я укоротил
источник

АК

Александр Караев... in cxx.Дискуссионная
Ofee
Короче, конструктор = default;, а компилируем юзер-код с максимально разными вариациями предефайн макроса и наличием/отсутствием агрегатной инициализации
и всё это компилим в один файл?
источник

O

Ofee in cxx.Дискуссионная
Александр Караев
и всё это компилим в один файл?
Там же написан вызов. foo.cpp в шаред либу, все остальные исходники — в разные исполняемые файлы
источник

O

Ofee in cxx.Дискуссионная
Ofee
Там же написан вызов. foo.cpp в шаред либу, все остальные исходники — в разные исполняемые файлы
На практике же я отдаю библиотеку юзеру-суициднику и он вообще может стрелять с её помощью себе в ноги так, как только ему заблагорассудится
источник

АК

Александр Караев... in cxx.Дискуссионная
я думаю, что стандарт не знает ничего про динамические библиотеки
источник

АК

Александр Караев... in cxx.Дискуссионная
он знает только про статическую линковку
источник

O

Ofee in cxx.Дискуссионная
Александр Караев
он знает только про статическую линковку
Однако, это не отменяет вопроса, делаем ли мы что-то ужасное. Но тогда допустим, что мы это линкуем всё в один файл
источник

АК

Александр Караев... in cxx.Дискуссионная
Ofee
Однако, это не отменяет вопроса, делаем ли мы что-то ужасное. Но тогда допустим, что мы это линкуем всё в один файл
на практике ужасное произойдёт, если линкер увидит разные тела инлайн конструкторов и выберет одно понравившееся
источник

АК

Александр Караев... in cxx.Дискуссионная
а может быть заинлайнит все вызовы и будут разные
источник

O

Ofee in cxx.Дискуссионная
Александр Караев
на практике ужасное произойдёт, если линкер увидит разные тела инлайн конструкторов и выберет одно понравившееся
Я чувствую, что я не понял и мне нужно пояснение того, что скрывается за фразой инлайн конструктор
Или же тут имелось ввиду просто "определённый в теле класса"?
источник

АК

Александр Караев... in cxx.Дискуссионная
Ofee
Я чувствую, что я не понял и мне нужно пояснение того, что скрывается за фразой инлайн конструктор
Или же тут имелось ввиду просто "определённый в теле класса"?
если метод (в том числе конструктор) определён в теле класса, он автоматически помечается inline
то есть, если ты просто напишешь в хедере struct A { A() = default; }; или даже struct A {};, ты автоматом получишь код:
inline constexpr A() noexcept = default;

то есть конструктор помечен как inline и любое обращение к нему - вызов inline функции. Соответственно, твой макрос приводит к тому, что этот конструктор может иметь разное тело
источник

АК

Александр Караев... in cxx.Дискуссионная
поэтому твой вопрос можно упростить до:

inline int f() { return SOME_MACRO; }
источник

O

Ofee in cxx.Дискуссионная
Александр Караев
если метод (в том числе конструктор) определён в теле класса, он автоматически помечается inline
то есть, если ты просто напишешь в хедере struct A { A() = default; }; или даже struct A {};, ты автоматом получишь код:
inline constexpr A() noexcept = default;

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

АК

Александр Караев... in cxx.Дискуссионная
ты написал:
> Я не знаю, inline ли он :)

знаешь, конечно же
источник

АК

Александр Караев... in cxx.Дискуссионная
я предположил, что ты можешь не знать, т.к. перепутал inline и инлайнинг
источник