Imitating fortran print and write syntaxes in C++

149 views Asked by At

I am trying to implement a class in C++ to imitate the syntax of the print and write statements from FORTRAN.

In order to achieve this, I implemented a class fooprint and overloaded fooprint::operator, (comma operator). Since this class should print to the standard output or to a file, I also defined two macros: print (for stdout) and write (to operate on files).

I get compilation errors when trying to use write(data) a; (see below for error log). How can I get a working write statement with the above properties?

This is the code (Live Demo):

#include <iostream>
#include <fstream>

class fooprint
{
    private:
      std::ostream *os;

    public:
      fooprint(std::ostream &out = std::cout) : os(&out) {}
      ~fooprint() { *os << std::endl;}

      template<class T>
      fooprint &operator, (const T output)
      {
        *os << output << ' ';
        return *this;
      }
};

#define print      fooprint(),     // last comma calls `fooprint::operator,`
#define write(out) fooprint(out),

int main()
{
  double a = 2.0;

  print "Hello", "World!";        // OK
  print "value of a =", a;        // OK
  print a;                        // OK

  std::ofstream data("tmp.txt");
  write(data) "writing to tmp";   // compiles with icpc; it doesn't with g++ 
  write(data) a;                  // this won't compile
  data.close();
  return 0;
}

And the compilation message:

g++ -Wall -std=c++11 -o print print.cc
   error: conflicting declaration ‘fooprint data’
   #define write(out) fooprint(out),
                                   ^
   note: in expansion of macro ‘write’
     write(data) a;
     ^
   error: ‘data’ has a previous declaration as ‘std::ofstream data’
   error: conflicting declaration ‘fooprint a’
     write(data) a;
                 ^
   error: ‘a’ has a previous declaration as ‘double a’

icpc -Wall -std=c++11 -o print print.cc
   error: "data" has already been declared in the current scope
     write(data) a;
   error: "a" has already been declared in the current scope
     write(data) a;
1

There are 1 answers

0
David G On BEST ANSWER

fooprint(out) is not the creation of a temporary but rather the declaration of a variable of type fooprint with the name provided as the argument to the macro. In order to not make this a declaration, and instead an expression, two quick changes you can make are surrounding it in parenthesis (fooprint(out)) or using brace-initialization (C++11) (fooprint{out}).