Я провожу небольшое исследование существующих способов нарушить ODR (Правило Единого Определения) при использовании inline, и меня интересует следующее.
У меня есть некоторые сомнения в том, в какой последовательности происходит препроцессинг и условная компиляция. Например, include и ifdef. Буду благодарен, если кто-нибудь сможет уточнить этот момент.
Можно ли нарушить ODR при использовании условной компиляции в inline функциях/методах?
Например:
func.hpp:
inline void func()
{
// ...
#ifdef X
// ...
#endif
// ...
}
a.cpp:
#define X
#include "func.hpp"
void a_func()
{
func();
}
b.cpp:
#undef X
#include "func.hpp"
void b_func()
{
func();
}
Я полагаю, что сначала происходит подстановка содержимого файла (в местеinclude), а уже потом - условная компиляция. Следовательно, данный код нарушает ODR и приводит к неопределенному поведению. Все происходит именно так?
Можно ли избавиться от нарушения ODR, если define и include поменять местами?
1. Я так понимаю, вопрос в том, видно ли в заголовочных файлах макросы, определенные в тех файлах, которые эти заголовки включают? Да, конечно видно. Иначе, например, include guard'ы бы не работали.
В вашем примере, #define X в a.cpp влияет на #ifdef X в func.hpp. (Конечно, если #define X находится выше #include "func.hpp")
2. Да, тут ODR нарушен.
3. Да, это уберет нарушение ODR, потому что функции станут одинаковыми. #ifdef X будет обработан раньше, чем #define X.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей