Imitating fortran print and write syntaxes in C++ - c++

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;

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}).

Related

Why do C++ deprecated warnings print twice?

If I have
namespace foo {
inline int bar() {
return 1119;
}
}
__attribute__((deprecated)) inline int bar() {
return 138;
}
in header.h and
#include "header.h"
#include <iostream>
int main() {
int x = bar();
int y = foo::bar();
std::cout << x << std::endl;
std::cout << y << std::endl;
}
in source.cpp, then
g++ source.cpp -o deprecated-test
results in
source.cpp: In function ‘int main()’:
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
int x = bar();
^
In file included from source.cpp:1:
header.h:7:40: note: declared here
__attribute__((deprecated)) int bar() {
^~~
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
int x = bar();
^
In file included from source.cpp:1:
header.h:7:40: note: declared here
__attribute__((deprecated)) int bar() {
(on Ubuntu 18.10 with g++ 8.2.0).
Why does the deprecated warning print twice?
Heading off some suggestions that would be unhelpful:
[[deprecated]]:
I know with C++14 on you can use the [[deprecated]] attribute, but I need to work with C++11.
Declaration vs. definition: The docs seem to imply it should be used with function declaration rather than definition, but
I need to define the functions inline in a header rather than declare in the header and define in source files; and
Trying this approach didn't stop the warning from printing twice anyway.
As per the documentation of GCC 8.2.0:
The deprecated attribute results in a warning if the function is used anywhere
in the source file. This is useful when identifying functions that are expected
to be removed in a future version of a program. The warning also includes the
location of the declaration of the deprecated function, to enable users to easily
find further information about why the function is deprecated, or what they
should do instead. Note that the warnings only occurs for uses...
There should be only one warning and not two. So this is a bug in GCC.
There is a related bug for Type attributes (rather than Function attributes) titled: C/C++ __attribute__((deprecated)) does not appear to wrap declarations as implied from the doc.
It has been confirmed as a bug.

How to declare a reference to a member in the same class?

I looked at a lot of other questions and answers and no one seems to have the same question I do.
I am trying to make references to variables, both within a class. I took out the part of the larger program I am writing and isolated it in a little file: test.cpp. I thought maybe my problem had something to do with how I was using the variable with the reference, but the same messages appeared as in the larger program.
Here is my code:
#include <iostream>
class Test {
public:
int test;
int& rtest = test;
};
int main() {
std::cout << "Enter an integer: ";
std::cin >> Test.rtest;
std::cout << "\n" << Test.rtest << "\n";
return 0;
}
I received these messages:
warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11
int& rtest = test;
In function ‘int main()’: error: expected primary-expression before ‘.’ token
std::cin >> Test.rtest;
error: expected primary-expression before ‘.’ token std::cout << "\n" << Test.rtest << "\n";
Why am I getting these? Is what I am trying to do possible? If so, how can I do it?
warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 int& rtest = test;
You need to pass the flag -std=c++11 to your compiler, otherwise it defaults to an older version of C++ which doesn't allow you to initialize class members in that way.
In function ‘int main()’: error: expected primary-expression before ‘.’ token std::cin >> Test.rtest;
error: expected primary-expression before ‘.’ token std::cout << "\n" << Test.rtest << "\n";
This is because the . operator wants an instance of your class, not the class itself (that's what :: would be for). Declare e.g. Test test; and use test.rtest instead.
You need to have an instance of Test to access non static members of a class:
int main() {
Test t; // <<<<<<<<
std::cout << "Enter an integer: ";
std::cin >> t.rtest;
std::cout << "\n" << t.rtest << "\n";
}
Also you need to initialize the reference with an appropriate constructor, unless you have the -std=c++11 compiler flag enabled as the error message says:
class Test {
public:
int test;
int& rtest; // Nope! = test;
Test() : test(), rtest(test) {} // <<<<<<<<<<<<<<<<<<
};

Passing a function object to a constructor [duplicate]

This question already has an answer here:
Pass anonymous function object to std::function?
(1 answer)
Closed 7 years ago.
What I am trying to achieve is to make a functor that can take different functors as arguments.
Edit: the reason for my problem, the "most vexing parse", and the solution are well-described: see this question and answer, the whole most-vexing-parse tag, and even the wikipedia page. Still, I was not able to identify the problem before asking, and will leave this question as it might help others.
What I did:
In a header file functor.hpp:
#ifndef FUNCTOR_HPP
#define FUNCTOR_HPP
#include <functional>
template <typename T, typename BinOp = typename std::plus<T>>
struct doer {
BinOp op;
doer(BinOp o = std::plus<T>()) : op(o) {}
T operator()(const T& a, const T& b) const
{ return op(a, b); }
};
#endif // FUNCTOR_HPP
With this header, I can write a program functor.cpp like this:
#include <iostream>
#include "functor.hpp"
int main()
{
doer<int> f;
std::cout << f(3, 7) << std::endl;
}
and I can compile and run it to get, as expected:
$ make functor
g++ -std=c++14 -pedantic -Wall functor.cpp -o functor
$ ./functor
10
$
I am struggling to find a way to instantiate my doer with a different operator (not std::plus<T>).
doer<int, std::multiplies<int>> f2(std::multiplies<int>());
This compiles without a problem, but I have not been able to figure out a way to call f2(3, 7), to get the product 21. For example, if I add another line to the program:
int r = f2(3, 7);
and try to compile, I get:
$ make functor
g++ -std=c++14 -pedantic -Wall functor.cpp -o functor
functor.cpp: In function ‘int main()’:
functor.cpp:10:20: error: invalid conversion from ‘int’ to ‘std::multiplies<int> (*)()’ [-fpermissive]
int r = f2(3, 7);
^
functor.cpp:10:20: error: too many arguments to function ‘doer<int, std::multiplies<int> > f2(std::multiplies<int> (*)())’
functor.cpp:9:37: note: declared here
doer<int, std::multiplies<int>> f2(std::multiplies<int>());
^
functor.cpp:10:20: error: cannot convert ‘doer<int, std::multiplies<int> >’ to ‘int’ in initialization
int r = f2(3, 7);
^
What is going on? Seems almost like f2(3, 7) somehow is not calling the overloaded operator()...
Most vexing parse. Try this:
doer<int, std::multiplies<int>> f2((std::multiplies<int>()));
or this:
doer<int, std::multiplies<int>> f2 = std::multiplies<int>();
or this:
doer<int, std::multiplies<int>> f2{std::multiplies<int>()};

Expression list treated as compound expression

I'm trying to compile a program I got from the net. Trying to use in codeblocks but its showing errors. I don't understand what is going wrong. I've looked up in various forums but not much light is shed. Can anyone help soon? Thanks in advance
#include <functional>
#include <iostream>
int print_num(int i, int j) { return i + j; }
int main() {
std::function<int(int, int)> foo = print_num;
std::function<int(int, int)> bar;
try {
std::cout << foo(10, 20) << '\n';
std::cout << bar(10, 20) << '\n';
} catch (std::bad_function_call& e) {
std::cout << "ERROR: Bad function call\n";
}
return 0;
}
These are some of the errors other than 14 other errors saying declaration not done. I guess clearing these error would solve that problem.
main.cpp|10|error: 'function' is not a member of 'std'
main.cpp|10|error: expression list treated as compound expression in functional cast [-fpermissive]
main.cpp|10|error: expected primary-expression before 'int'
You need to compile with -std=c++11 to add in the C++11 features.
$ g++ -std=c++11 test.cxx && ./a.out
30
ERROR: Bad function call
vs:
$ g++ test.cxx && ./a.out
test.cxx: In function ‘int main()’:
test.cxx:10:3: error: ‘function’ is not a member of ‘std’
test.cxx:10:28: error: expression list treated as compound expression in functional cast [-fpermissive]
test.cxx:10:17: error: expected primary-expression before ‘int’
...

Understanding 'using' keyword : C++

Can someone please explain below output:
#include <iostream>
using namespace std;
namespace A{
int x=1;
int z=2;
}
namespace B{
int y=3;
int z=4;
}
void doSomethingWith(int i) throw()
{
cout << i ;
}
void sample() throw()
{
using namespace A;
using namespace B;
doSomethingWith(x);
doSomethingWith(y);
doSomethingWith(z);
}
int main ()
{
sample();
return 0;
}
Output:
$ g++ -Wall TestCPP.cpp -o TestCPP
TestCPP.cpp: In function `void sample()':
TestCPP.cpp:26: error: `z' undeclared (first use this function)
TestCPP.cpp:26: error: (Each undeclared identifier is reported only once for each function it appears in.)
I have another error:
error: reference to 'z' is ambiguous
Which is pretty clear for me: z exists in both namespaces, and compiler don't know, which one should be used. Do you know? Resolve it by specifying namespace, for example:
doSomethingWith(A::z);
using keyword is used to
shortcut the names so you do not need to type things like std::cout
to typedef with templates(c++11), i.e. template<typename T> using VT = std::vector<T>;
In your situation, namespace is used to prevent name pollution, which means two functions/variables accidently shared the same name. If you use the two using together, this will led to ambiguous z. My g++ 4.8.1 reported the error:
abc.cpp: In function ‘void sample()’:
abc.cpp:26:21: error: reference to ‘z’ is ambiguous
doSomethingWith(z);
^
abc.cpp:12:5: note: candidates are: int B::z
int z=4;
^
abc.cpp:7:5: note: int A::z
int z=2;
^
which is expected. I am unsure which gnu compiler you are using, but this is an predictable error.
You get a suboptimal message. A better implementation would still flag error, but say 'z is ambiguous' as that is the problem rather than 'undeclared'.
At the point name z hits multiple things: A::z and B::z, and the rule is that the implementation must not just pick one of them. You must use qualification to resolve the issue.