How to compare two std::istream references? - c++

I am switching over compilers from GCC to Clang/LLVM and running into compilation errors I didn't experience before.
I have a class that looks something like this:
#include <iostream>
class foo {
public:
bar(std::istream& is) : _fp(is), _sCheck(is != std::cin) { /* ... */ }
private:
std::istream& _fp;
bool _sCheck;
}
When I compile this file, I get the following error with clang++, where the initialization of the private variable _sCheck fails:
error: invalid operands to binary expression ('std::istream' (aka
'basic_istream<char>') and 'istream' (aka 'basic_istream<char>'))
(is != std::cin)
~~ ^ ~~~~~~~~
If both objects in this address comparison are of the same type, why is clang++ returning an error, while g++ does not?
I tried a dynamic_cast to make them both std::istream&, but this, too, returned an error:
error: invalid operands to binary expression ('std::istream' (aka
'basic_istream<char>') and 'std::istream')
(is != dynamic_cast<std::istream&>(std::cin))
~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I apologize in advance if this is a dumb question; I appreciate any pointers.

You are using references, so you are comparing the objects and not the pointers as you maybe intended to. It seems GCC has an extension which allows you to compare std::istream objects, but this is not part of the standardized interface of std::basic_istream. Try:
_sCheck(&is != &std::cin)

Related

Unit testing a vector string

I have this really simple line of code in my production-code(A.cpp) as follows:
std::string A::getString(int i) {
return sVect_[i];
}
with the header as follows:
class A{
public:
std::string getString(int i);
...
private:
vector<std::string> sVect_;
...
};
I've been trying to test the getString() function using googletest but an error keeps popping out:
error: invalid conversion from 'char* (*)(const char*, int)throw ()' to 'int'
error: initializing argument 1 of 'std::string A::getString(i)'
This was my test program:
TEST(ATest, getString){
A a;
EXPECT_EQ("c", a.getString(i));
}
I couldn't quite grasp the workaround of the vector string and how to call it in my test program without ever changing the production code. I even use the hack, adding #define statements, to access the private member but still couldn't do it.
How do my test actually looks like to successfully call that function?
Note: I'm on Linux and using gcc. Thank you in advance guys.
Perhaps the error message is misleading. Have you defined i globally somewhere else? To me it looks like in the local scope because it does not know what the value of the variable i is, it is misbehaving in an unexpected way
TEST(ATest, getString){
A a;
EXPECT_EQ("c", a.getString(i)); //here what is the 'i' and where is it defined
}

error: cannot convert 'std::basic_string<char>::iterator ...' to 'const char* for argument '1' ...'

I'm getting the following error:
error: cannot convert 'std::basic_string<char>::iterator {aka __gnu_cxx::__normal
_iterator<char*, std::basic_string<char> >}' to 'const char*' for argument '1'
to 'int remove(const char*)'
For some reason, my program compiles perfectly when I'm working on a Mac... but once I use a Linux machine, this error pops up in more than one place.
Here's one of the instances where the error pops up:
SomeClass::SomeClass(string t, string art, Time dur) {
char chars[] = ",";
t.erase(std::remove(t.begin(), t.end(), chars[0]), t.end());
art.erase(std::remove(art.begin(), art.end(), chars[0]), art.end());
// Some more code ...
}
More specifically, the error is coming from this line:
t.erase(std::remove(t.begin(), t.end(), chars[0]), t.end());
Does anyone know how to approach this problem?
You forgot to #include <algorithm>, where std::remove is located. Without that, your compiler only knows about this std::remove (I get the same error with Visual C++ 14), which is defined in indirectly included <cstdio> header.
Different behavior among compilers is a result of different #include hierarchies of the standard library implementations.

Vector of pointer member functions c++

I have the following code:
typedef bool (A::*rule)(shared_ptr<Node >, shared_ptr<Node> ) ;
when initilaising the class A object, I run the following code
v_ = vector<rule>();
v_.push_back(A::memberFunction);
I have also tried with v_.push_back(&A::memberFunction) as this seemed more logical to me, but was
advised against on the forums. I also get an error message
This is as suggested by the many topics on the matter. However, I get the following error
non-const lvalue reference to type 'value_type' (aka 'bool (boost::shared_ptr<Node>, boost::shared_ptr<Node>)')
cannot bind to a temporary of type '<bound member function type>'
Does anyone know where I am going wrong?
I have also tried with v_.push_back(&A::memberFunction) as this seemed more logical to me, but was advised against on the forums.
I don't know what forums were those. Forming a pointer-to-member has a single valid syntax, and it is & classname::membername. All elements mandatory.
Use that consistently and post code and error message for that version should the problem persist.
This code compiles under llvm/clang 4.2 (As #balog-pal said, the & is mandatory before classname::membername:
#include <memory>
#include <vector>
struct Node {};
struct A
{
bool rule(std::shared_ptr<Node>, std::shared_ptr<Node>)
{return true;}
};
typedef bool (A::*rule)(std::shared_ptr<Node>, std::shared_ptr<Node> );
int main(int, const char**)
{
std::vector<rule> v;
v.push_back(&A::rule);
return 0;
}
Please post a full not-compiling example, your issue must be hidden somewhere else.

Passing fstream reference as function parameter in C++11

I've just encountered an problem today: The following code seems to work in MSVC++ 2010 but not with Clang LLVM 4.1 (with GNU++11).
#include <fstream>
void foo(std::fstream& file){
file << "foo";
}
int main() {
std::fstream dummy("dummy");
foo(dummy);
return 0;
}
generates
Invalid operands to binary expression (std::fstream (aka basic_fstream<char>) and const char[4])
on Clang. I thought passing iostream arguments by reference would be common practice in C++. I'm not even sure if this is related to clang, C++11 or anything else.
Any idea how I can pass streams to functions then?
I assume that your original code (that you only partially posted in your original question) looked something like this:
#include <iosfwd>
void foo(std::fstream& file){
file << "foo";
}
int main() {
std::fstream dummy("dummy");
foo(dummy);
return 0;
}
Indeed, this gives the following error message with clang++ 3.2
Compilation finished with errors:
source.cpp:4:10: error: invalid operands to binary expression ('std::fstream' (aka 'basic_fstream<char>') and 'const char [4]')
file << "foo";
~~~~ ^ ~~~~~
source.cpp:8:17: error: implicit instantiation of undefined template 'std::basic_fstream<char, std::char_traits<char> >'
std::fstream dummy("dummy");
^
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/iosfwd:118:11: note: template is declared here
class basic_fstream;
^
2 errors generated.
Unfortunately, you only posted the first error message but not the second.
From the second error message, it is obvious that you only #include <iosfwd> but not #include <fstream>. If you fix that, everything will be OK.
Please post both the complete code and all the error messages next time.

Invalid conversion to non-const reference in C++0x... bug in std::pair?

I have been developing a library that is getting pretty large, and now I am adding some template-based parts that use C++0x features. So I tried to compile my library (which compiled entirely without warnings on the current standard) with the flag -std=c++0x using gcc version 4.4.5 (on Linux). Now I got a huge influx of error messages related to the conversion of "temporaries" variables to non-const references. The problem is, they are not temporary!
Here is a small piece of code that reproduces the error:
#include <iostream>
#include <map>
struct scanner {
scanner& operator &(std::pair<std::string, int&> i) {
std::cout << "Enter value for " << i.first << ": ";
std::cin >> i.second;
return *this;
};
};
struct vect {
int q[3];
void fill(scanner& aScan) {
aScan & std::pair<std::string, int&>("q0",q[0])
& std::pair<std::string, int&>("q1",q[1])
& std::pair<std::string, int&>("q2",q[2]);
};
};
int main() {
vect v;
scanner s;
v.fill(s);
return 0;
};
If you compile this with the current standard (no c++0x flag) it will compile and run as expected. However, if you compile it with -std=c++0x, it will throw the following error at compile-time:
/usr/include/c++/4.4/bits/stl_pair.h:94: error: invalid initialization of non-const reference of type ‘int&’ from a temporary of type ‘int’
I really can't figure this out. I have looked over the web and SO, but none seem to have this problem. Is it a bug in std::pair? I would really like to know what the problem is.. thank you for any insight you can give.
PS: don't complain about the "quality" or "stupidity" of the code above, it is not real code.. just an example that shows the error.
Your code is not valid C++03, comeau gives (after adding a return statement to op&):
"stl_pair.h", line 44: error: qualifiers dropped in binding reference of
type "int &" to initializer of type "const int"
pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) {}
^
detected during instantiation of "std::pair<_T1, _T2>::pair(const
_T1 &, const _T2 &) [with _T1=std::string, _T2=int &]" at
line 17 of "ComeauTest.c"
...
The problem is a reference inside a pair. If I remember correctly, it is a gcc extension that allows this. Gcc does accept it with -std=gnu++98, which is the default for C++, but with -std=c++98, gcc 4.4.3 gives:
In file included from /usr/include/c++/4.4/bits/stl_algobase.h:66,
from /usr/include/c++/4.4/algorithm:61,
from PREAMBLE:7:
/usr/include/c++/4.4/bits/stl_pair.h: In instantiation of ‘std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int&>’:
<input>:5: instantiated from here
/usr/include/c++/4.4/bits/stl_pair.h:83: error: forming reference to reference type ‘int&’
...
There are LOTS of bugs in gcc C++0x support, it's very much unfinished and development is ongoing. This is doubly true for a version as old as gcc-4.4.5. If you're serious about starting C++0x development before the standard is ratified, you need to use the bleeding-edge version of the compiler and standard library.
It compiles fine both with and without -std=c++0x with GCC 4.5.2.
I guess GCC 4.4.5 doesn't support C++0x that much to get this working.
Except for the missing return *this; in scanner& operator &(std::pair<std::string, int&> i), your code is valid C++0x.