Я пытаюсь использовать один и тот же класс в С++ и С#. Я использую директивы препроцессора, чтобы избежать различий в коде. Однако я не могу пропустить директивы C++ (например, #include или #define), даже если они находятся внутри раздела #if#endif.
Следующий код компилируется на C++, но не на C#:
#if !NET
#pragma once
#include <string> //<-- C# error CS1024: Preprocessor directive expected
#define public public: //<-- C# error CS1025: Single-line comment or end-of-line expected
#endif
#if NET
namespace A.B {
#else
namespace A::B {
using namespace std;
#endif
class C {
string str;
public C() {str = "test";}
};
}
#if !NET
#undef public
#endif
Вопросы:
#include или #define, если они находятся внутри секции #if !NET?Ой! Перечитывая главу 6.5.5 стандартной спецификации C#, я замечаю следующий абзац:
Любые оставшиеся условные разделы пропускаются, и из исходного кода не генерируются никакие токены, за исключением директив предварительной обработки. Поэтому пропущенный исходный код, за исключением директив предварительной обработки, может быть лексически некорректным. Пропущенные директивы предварительной обработки должны быть лексически правильными, но в противном случае они не обрабатываются. В условном разделе, который пропускается, любые вложенные условные разделы (содержащиеся во вложенных конструкциях
#if...#endif) также пропускаются.
Я знаю. Это пример кода. Цель состоит в том, чтобы задать вопрос о пропуске директив C++ при написании кода на C# как можно проще.
Возможно, «препроцессор» С# просто не работает как препроцессор С++? Что говорит его документация?
Кроме того, когда вы заставите это работать, пожалуйста, никогда не делайте этого снова! Это просто плохо, и никто в здравом уме не захочет даже смотреть на такой код.
Как определить макрос? #if !NET истинно, если NET определяется как #define NET или -D NET. Присвойте ему какое-то ненулевое значение или используйте #ifndef NET
Учитывая сильно отличающийся синтаксис, почти всегда плохая идея даже пытаться это сделать.
Я полагаю, @273K -D определяет макрос как 1 по умолчанию.
@HolyBlackCat Приятно это знать, мои аргументы командной строки можно уменьшить.
Может быть, я глуп, но я не понимаю, почему вы хотите скомпилировать один и тот же файл как для C++, так и для C#. Почему бы вам просто не создать два разных файла и не скомпилировать каждый как отдельный язык?
Я вижу, что опечатка в одном #endif может действительно все испортить, поэтому требование только действительных директив кажется разумным. Кроме того, в C++ специально запрещено использование #define для изменения ключевых слов, таких как private.
@JesperJuhl Я разрабатываю инструмент, в котором внешний интерфейс — это C#, а внутренний — C++, и обоим нужны общие классы. В настоящее время у меня есть два файла для каждого общего класса, один для C++, другой для C#, и когда я что-то меняю в одном файле, мне нужно помнить об изменении в другой стороне. Я пытаюсь смешать оба файла в один, чтобы улучшить ремонтопригодность и отслеживаемость.





Наконец, я нашел способ решить эту проблему, используя два файла:
Примечание. Возможно, это не лучшая идея, но я не могу найти ничего лучше, чем эта.
/*** myfile.hpp ***/
#pragma once
#include <string>
#define public public:
#include "myfile.cs"
#undef public
/*** myfile.cs ***/
#if NET
namespace A.B {
#else
namespace A::B {
using string = std::string;
#endif
class C {
string str;
public C() {str = "test";}
};
}
С этими двумя файлами на C++ должен быть включен myfile.hpp, а на C# нужен только myfile.cs.
Идея взята отсюда: https://stackoverflow.com/a/56839291/13087883
OT: Почему "используя пространство имен std;" считается плохой практикой? Делать это в заголовочном файле просто неправильно (IMO)