Search code examples
c++loggingmacrosgcc-extensions

Simple c++ program gets compilation errors


When I'm trying to compile this code, it shows error:

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

This is the file:

#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;
}

$ is simple name of DEBUG, in runtime it's 0 or 1.

The compilation error is for this source file. how to get rid of this and compile?


Solution

  • There are some things you're doing here that are inadvisable, and some that are illegal. But I gave you an upvote for at least alerting me to a gcc extension I hadn't seen:

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

    That does indeed output on IDEone I'm surprised this prints 30, even under C++14 settings. On coliru, though you get:

    main.cpp:4:17: warning: ISO C++ forbids braced-groups within expressions [-Wpedantic]

    Yet now that we've had our learning moment together, avoid non-standard extensions. Partly because people on StackOverflow will yell at you. But mostly for the reasons that life is hard enough trying to find terra firma in language development, education and usage when you stick to the subset that has been agreed upon and vetted by a large number of people who thought through the issues.

    (The "language feature that one guy added that time for that project" is probably a bad idea--for any definition of "that one guy" or "that project".)

    Also, something like that--being rarely used--probably has all kinds of lack of attention in the optimizer about getting that expression out. Which means at best it's slower than other ways, and at worst it has random bugs.


    Moving on:

    • The use of $ in identifier names is apparently "implementation-defined behavior". Meaning there's nothing in the spec disallowing it...but nothing saying that a compiler has to implement it either. It's probably not something you want to be inventing new creative uses of, and only using if you're stuck in a situation bridging with old code on a VAX or something.

    • On the other hand, you simply you can't name any global variables or macros starting with an underscore. They are reserved for compiler implementations to use themselves. (If you read all that you'll see other unusual nuances, such as that you can't have identifiers beginning with an underscore and followed by a capital letter in ANY scope, although if the letter is lowercase you can define them locally. Often people use this for member variables but have to be careful to follow the rule.)

    • It's possible to use printf for purposes of compatibility...because of the explicit design to enable taking old C programs and slowly upgrade them to C++. But you shouldn't be writing new constructs or code using it, and if you want some basic philosophy on why then read the short paper Learning Standard C++ as a New Language. It's an old paper in its own right, but it's from Bjarne Stroustrup and works through that particular point pretty well.

    Yet the "biggest" issue of why the approach is generally wrong is that there are much more reliable ways of doing this than trying to grab textual swaths of code into a macro. Many topics to study on that, such as the use of lambdas in C++11. But more generally you should focus on what appears to be your desire here, which is the subject area of logging. A quick search into a tag intersection could get you good advice on that:

    Search Query for [c++] [logging] __FILE__

    how to get rid of this and compile?

    Introduce intermediate steps into the process.

    1. Get rid of this...(code!)
    2. Read through the links I've provided.
    3. Look at approaches used to achieve this goal and assess what you like or don't like about them.
    4. Write new code that uses better practices, or borrow from others.
    5. ...and compile. :-)