Как пропустить директиву препроцессора C++ в C#

Я пытаюсь использовать один и тот же класс в С++ и С#. Я использую директивы препроцессора, чтобы избежать различий в коде. Однако я не могу пропустить директивы 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

Вопросы:

  • Почему я не могу этого сделать?
  • Почему препроцессор C# пытается понять директивы #include или #define, если они находятся внутри секции #if !NET?
  • Есть ли способ это сделать?

Обновлено:

Ой! Перечитывая главу 6.5.5 стандартной спецификации C#, я замечаю следующий абзац:

Любые оставшиеся условные разделы пропускаются, и из исходного кода не генерируются никакие токены, за исключением директив предварительной обработки. Поэтому пропущенный исходный код, за исключением директив предварительной обработки, может быть лексически некорректным. Пропущенные директивы предварительной обработки должны быть лексически правильными, но в противном случае они не обрабатываются. В условном разделе, который пропускается, любые вложенные условные разделы (содержащиеся во вложенных конструкциях #if...#endif) также пропускаются.

  • Итак, хорошо, мой первый вопрос дан ответ.
  • А как насчет второго: почему директивы предварительной обработки должны быть лексически правильными?
  • Однако кто-нибудь знает, как обойти это ограничение? Как заставить приведенный выше код работать?

OT: Почему "используя пространство имен std;" считается плохой практикой? Делать это в заголовочном файле просто неправильно (IMO)

Some programmer dude 08.06.2023 18:17

Я знаю. Это пример кода. Цель состоит в том, чтобы задать вопрос о пропуске директив C++ при написании кода на C# как можно проще.

Sergio Pérez Beltrán 08.06.2023 18:23

Возможно, «препроцессор» С# просто не работает как препроцессор С++? Что говорит его документация?

Some programmer dude 08.06.2023 18:24

Кроме того, когда вы заставите это работать, пожалуйста, никогда не делайте этого снова! Это просто плохо, и никто в здравом уме не захочет даже смотреть на такой код.

Some programmer dude 08.06.2023 18:25

Как определить макрос? #if !NET истинно, если NET определяется как #define NET или -D NET. Присвойте ему какое-то ненулевое значение или используйте #ifndef NET

273K 08.06.2023 18:27

Учитывая сильно отличающийся синтаксис, почти всегда плохая идея даже пытаться это сделать.

Charlieface 08.06.2023 18:43

Я полагаю, @273K -D определяет макрос как 1 по умолчанию.

HolyBlackCat 08.06.2023 19:27

@HolyBlackCat Приятно это знать, мои аргументы командной строки можно уменьшить.

273K 08.06.2023 20:19

Может быть, я глуп, но я не понимаю, почему вы хотите скомпилировать один и тот же файл как для C++, так и для C#. Почему бы вам просто не создать два разных файла и не скомпилировать каждый как отдельный язык?

Jesper Juhl 08.06.2023 21:51

Я вижу, что опечатка в одном #endif может действительно все испортить, поэтому требование только действительных директив кажется разумным. Кроме того, в C++ специально запрещено использование #define для изменения ключевых слов, таких как private.

BoP 08.06.2023 22:57

@JesperJuhl Я разрабатываю инструмент, в котором внешний интерфейс — это C#, а внутренний — C++, и обоим нужны общие классы. В настоящее время у меня есть два файла для каждого общего класса, один для C++, другой для C#, и когда я что-то меняю в одном файле, мне нужно помнить об изменении в другой стороне. Я пытаюсь смешать оба файла в один, чтобы улучшить ремонтопригодность и отслеживаемость.

Sergio Pérez Beltrán 09.06.2023 09:52
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
11
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Наконец, я нашел способ решить эту проблему, используя два файла:

Примечание. Возможно, это не лучшая идея, но я не могу найти ничего лучше, чем эта.

/*** 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

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