Принудительно включить один включаемый файл перед другим

Представь у меня два .hpp файлы:

#ifndef _DEF_FILE_1_
#define _DEF_FILE_1_
inline void some_function_1(){
    /*do stuff*/
}
#endif

а также

#ifndef _DEF_FILE_2_
#define _DEF_FILE_2_
#ifdef _DEF_FILE_1_
inline void some_function_2(){
    /*do stuff using some_function_1()*/
}
#else
inline void some_function_2(){
    /*do the same stuff without using some_function_1()*/
}
#endif
#endif

Моя проблема возникает, когда я не знаю, в каком порядке файлы включены, например: в main.cpp я могу иметь что-то вроде:

#include "file1.hpp"
#include "file2.hpp"
int main(){
    some_function_2();
    /*will call the function that uses some_function_1()*/
}

или же

#include "file2.hpp"
#include "file1.hpp"
int main(){
    some_function_2();
    /*will call the function that doesn't use some_function_1()*/
}

Есть ли способ убедиться, что как только file1.hpp а также file2.hppвключены, то some_function_2() позвоню some_function_1()?

PS: одним из решений было бы включить file1.hpp в file2.hpp но я не могу этого сделать, потому что я разработал код, который может зависеть или не зависеть от какой-то библиотеки, которую может иметь или не иметь конечный пользователь.

PPS: Единственное другое решение, которое я могу придумать (даже если я не знаю, как этого добиться), это "удалить" определение some_method_2() когдаfile1.hpp включен, а затем включить file2.hpp,

4 ответа

Я считаю, что правильным решением было бы переписать some_function_2() используя механизм и шаблон SFINAE вместо хитростей препроцессора. Таким образом, создание экземпляра будет происходить в файле cpp, где будет известно, если some_function_1() существует и порядок включения не имеет значения.

Ваши пользователи должны знать, есть ли у них "какая-то библиотека" или у вас должен быть какой-то способ определить, присутствует ли эта библиотека. Таким образом, вы можете сделать что-то вроде:

В file2.hpp

#ifndef _DEF_FILE_2_
#define _DEF_FILE_2_
#ifdef _DEF_HAS_SOME_LIBRARY_
#include "file1.hpp"
inline void some_function_2(){
    /*do stuff using some_function_1()*/
}
#else
inline void some_function_2(){
    /*do the same stuff without using some_function_1()*/
}
#endif
#endif

Или, если возможно, полностью исключить file1.hpp и поставить some_function_1() в месте нахождения #include "file1.hpp" выше.

Теперь main.cpp должен включать только file2.hpp.

// optionally #define _DEF_HAS_SOME_LIBRARY_
#include "file2.hpp"
int main(){
    some_function_2();
    /*will call the function that uses some_function_1()*/
}

хотя, решение, которое избегает препроцессора, было бы лучше по моему мнению.

Если вы не знаете, существует ли файл и должны это обработать, то ни препроцессор c, ни C++ не проверяют наличие файлов. Это одна из причин инструментов настройки.

Вам нужно предварительно проверить эту информацию и установить ее перед компиляцией. Есть много способов сделать это. Обычно инструмент / скрипт, создает некоторые configure.h Заголовок с соответствующими определениями создан. Например, содержащие такую ​​строку #define FILE1_HPP_EXISTS 1,

Тогда вы всегда можете рассчитывать на наличие configure.h и он предоставит необходимую вам информацию.

Если ваш компилятор это позволяет, вы можете использовать _has_include макрос:

Просто поменяю тебя file2.hpp чтобы:

#ifndef _DEF_FILE_2_
#define _DEF_FILE_2_

#if defined(__has_include) && __has_include("file1.hpp")
# include "file1.hpp"
inline void some_function_2() {
    /*do stuff using some_function_1()*/
}
#else
inline void some_function_2() {
    /*do the same stuff without using some_function_1()*/
}
#endif
#endif

Но имейте в виду, что это расширение для конкретного компилятора.

Другие вопросы по тегам