Простая программа на С ++ получает ошибки компиляции

Когда я пытаюсь скомпилировать этот код, он показывает ошибку:

main.cpp:19:3: error: invalid operands of types 'void' and 'int' to binary 'operator!='

Это файл:

#include <iostream>
#include <cstdio>
using namespace std;
#define $ DEBUG
#define DEBUG 1
#define _(out) do{  std::cout << __FILE__ << ":" << __LINE__ \
                       << " " << out << '\n';}while(0)
#define _(out) printf(out);
int main(){

#ifdef LOCAL_PROJECT
    #define DEBUG 0
#endif

    $ && ({
        _("eeeeewe");
    });//line 19

    return 0;
}

$ это простое имя DEBUGво время выполнения это 0 или же 1,

Ошибка компиляции для этого исходного файла. как от этого избавиться и скомпилировать?

2 ответа

Решение

Есть некоторые вещи, которые вы здесь делаете, которые нецелесообразны, а некоторые - незаконные. Но я дал вам ответ, по крайней мере, предупредив меня о расширении gcc, которого я не видел:

#include <iostream>

int main() {
    int x = ({std::cout << "I'm surprised this prints "; 10 + 20;});
    std::cout << x << "\n";
}

Это действительно вывод на IDEone I'm surprised this prints 30, даже в настройках C++14. На колиру, хотя вы получаете:

main.cpp: 4: 17: предупреждение: ISO C++ запрещает использование фигурных скобок в выражениях [-Wpedantic]

Но теперь, когда у нас был совместный учебный момент, избегайте нестандартных расширений. Отчасти потому, что люди на Stackru будут кричать на тебя. Но главным образом по причинам, по которым жизнь достаточно трудна, пытаясь найти terra firma в развитии языка, образовании и использовании, когда вы придерживаетесь подмножества, которое было согласовано и проверено большим количеством людей, которые продумали проблемы.

("Языковая особенность, которую один парень добавил в это время для этого проекта", вероятно, плохая идея - для любого определения "того одного парня" или "того проекта".)

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


Двигаясь дальше:

  • Использование $ в именах идентификаторов явно "поведение, определяемое реализацией". Это означает, что в спецификации ничего не запрещено, но ничего не говорит о том, что компилятор должен это реализовать. Это, вероятно, не то, что вы хотите изобретать новые творческие использования, а только если вы застряли в ситуации, связанной со старым кодом на VAX или чем-то еще.

  • С другой стороны, вы просто не можете назвать глобальные переменные или макросы, начинающиеся с подчеркивания. Они зарезервированы для реализаций компилятора для использования самих себя. (Если вы прочтете все, что увидите, вы увидите другие необычные нюансы, например, то, что у вас не может быть идентификаторов, начинающихся с подчеркивания и сопровождаемых заглавной буквой в ЛЮБОЙ области видимости, хотя если эта буква строчная, вы можете определить их локально. Часто люди используют это для переменных членов, но должны соблюдать осторожность, чтобы следовать правилу.)

  • Можно использовать printf в целях совместимости... из-за явного дизайна, позволяющего брать старые программы на C и медленно обновлять их до C++. Но вам не следует писать новые конструкции или код, использующий его, и если вы хотите получить некоторую базовую философию о том, почему, тогда прочитайте небольшую статью " Обучение стандарту C++ как новый язык". Это старая статья сама по себе, но она написана Бьярном Страуструпом и хорошо справляется с этой задачей.

Тем не менее, "самая большая" проблема того, почему этот подход в целом ошибочен, состоит в том, что есть гораздо более надежные способы сделать это, чем пытаться втиснуть текстовые фрагменты кода в макрос. Много тем для изучения, таких как использование лямбд в C++11. Но в более общем плане вы должны сосредоточиться на том, что кажется вам здесь желательным, а именно на предметной области ведения журнала. Быстрый поиск в пересечении тегов может дать вам хороший совет:

Поисковый запрос для[c++] [logging] __FILE__

как от этого избавиться и скомпилировать?

Введите промежуточные шаги в процессе.

  1. Избавьтесь от этого...(код!)
  2. Прочитайте ссылки, которые я предоставил.
  3. Посмотрите на подходы, используемые для достижения этой цели, и оцените, что вам нравится или не нравится в них.
  4. Напишите новый код, который использует лучшие практики, или позаимствуйте у других.
  5. ... и скомпилировать.:-)

Удалите точку с запятой после вызова макроса или просто измените макрос, чтобы удалить точку с запятой после printf(out).

Макросы особенно неудобны, когда они вызывают ошибки, подобные этой. Поскольку макросы заменяются напрямую, как find + copy + paste, иногда это может привести к результатам, которые не имеют смысла.

#include <iostream>
#include <cstdio>
using namespace std;
#define $ DEBUG
#define DEBUG 1
#define _(out) do{  std::cout << __FILE__ << ":" << __LINE__ \
                       << " " << out << '\n';}while(0)
#define _(out) printf(out);
int main(){

#ifdef LOCAL_PROJECT
    #define DEBUG 0
#endif

    $ && ({
        _("eeeeewe")
    });//line 19

    return 0;
}
Другие вопросы по тегам