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.
Related
Recently, I've started using MSVC to compile a code which was always compiled with GCC and Clang. Some piece of this code produces an interesting compilation error (truncated):
C:/data/msvc/14.33.31424-Pre/include\future(311) error C2678: binary '=': no operator found which takes a left-hand operand of type 'const Result' (or there is no acceptable conversion)
<source>(7): note: could be 'Result &Result::operator =(Result &&)'
<source>(7): note: or 'Result &Result::operator =(const Result &)'
Minimal example of this piece of code:
#include <future>
#include <iostream>
struct Result {
int data{0};
};
// getting rid of constness resolves the problem for MSVC
using result_t = const Result;
using promise_result_t = std::promise<result_t>;
auto compute_result(promise_result_t result)
{
Result some_result{10};
result.set_value(std::move(some_result));
}
int main()
{
promise_result_t my_promise;
auto my_future = my_promise.get_future();
std::thread thread(compute_result, std::move(my_promise));
std::cout << "result: " << my_future.get().data;
thread.join();
return 0;
}
Successful compilation with Clang 11: https://godbolt.org/z/o6Ge85rxG
Successful compilation with GCC 12: https://godbolt.org/z/x1rhqhfGT
Error with MSVC 19: https://godbolt.org/z/4jMYhTj3n
It is quite clear that removal of const for std::promise storage solves the problem, but I'm curious if anyone has tried to dive deep into the implementations of std::promise for different compilers.
What might be the difference that allows this code to compile and work using GCC and Clang, yet produce a compilation error when using MSVC? (Operating via pointers on stored data in GCC and Clang?)
Looks like an MSVC issue, reported here:
https://developercommunity.visualstudio.com/t/std::promise-works-incorrectly-for-const/10092031
and linked to the issue on GitHub:
https://github.com/microsoft/STL/issues/2599
In an old project code was a statement like:
cout.operator<<("Hi...");
ostream.operator<<("Hi....");
It argued that it can be written as followa, resulting in same output:
cout << "Hi..";
I have tried to put these statement in main(). But compiler gives error:
In function 'int main()':
11:3: error: 'ostream' was not declared in this scope
11:3: note: suggested alternative:
In file included from /usr/include/c++/4.9/ios:38:0,
from /usr/include/c++/4.9/ostream:38,
from /usr/include/c++/4.9/iostream:39,
from 2:
/usr/include/c++/4.9/iosfwd:136:33: note: 'std::ostream'
typedef basic_ostream<char> ostream;
The other thing that I am not convinced of is this statement that ostream can directly call operator<<. Same about cout that can it call operator<< directly.
If some body could elaborate or explain how, then I will able to debug the code.
Thanks.
The code line in question can actually ber compiled and does work, e.g:
#include <iostream>
using namespace std;
int main (void)
{
cout << "Hi"; // code line in question
cout << endl;
return 0;
}
The quoted error is caused by using ostream, which is the type of cout, in a place where an object (not a type) is required.
As also mentioned in a comment, the fix of that error is using an object of that type instead. Which basically means the first line of quoted code, i.e. the line in the solution code above.
I am porting some C++ code from Windows to Linux (and eventually OSX). Tons of C++ issues arise due to Windows non-compliance. I seem to have gotten past that, but am now facing a boost problem.
Basically, I want to chop up a string where the substrings of interest are separated by commas, and shove those into a string vector. This results in errors in g++, but it works fine compiling with Visual Studio
This program illustrates the issue exactly:
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
int main (void) {
std::vector<std::string> str_vec;
std::string str_to_split = "this,is,the,string,to,split";
boost::algorithm::split(str_vec,
str_to_split.substr(1, str_to_split.size()-2),
boost::algorithm::is_any_of(","),
boost::algorithm::token_compress_on);
return 0;
}
To compile I do: >> g++ -o foo foo.cpp
This is my terminal output:
foo.cpp: In function 'int main()':
foo.cpp:11:54: error: invalid initialization of non-const reference type 'std::basic_string<char>&' from an rvalue of type'std::basic_string<char>'
boost::algorithm::split(str_vec,str_to_split.substr(1, str_to_split.size()-2),boost::algorithm::is_an
^
In file included from /usr/include/boost/algorithm/string.hpp:23:0,
from foo.cpp:1:
/usr/include/boost/algorithm/string/split.hpp:140:35: note: initializing argument 2 of 'equenceSequenceT& boost::algorithm::split(SequenceSequenceT&, RangeT&, PredicateT, boost::algorithm::token_compress_mode_type) [with SequenceSequenceT = std::vector<std::basic_string<char> >; RangeT = std::basic_string<char>; PredicateT = boost::algorithm::detail::is_any_ofF<char>]'
inline SequenceSequenceT& split(
^
This function takes std::string& rather than std::string or const std::string&. That means you'll have to store the result of .substr in an intermediate variable then pass the variable to boost::algorithm::split. It'll be clearer code anyway.
FWIW, I have no idea why the function is designed this way. Seems odd to me but there you go.
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.
I am currently trying to get the following very simple boost::phoenix::lambda to compile:
#include <iostream>
#include <boost/phoenix/scope.hpp>
int main() {
boost::phoenix::lambda[std::cout << "Lambda!!"]();
}
However, this generates a host of errors (too much to post here), none which make any sense to me. Here is an excerpt of the compiler output:
error: 'std::ios_base::ios_base(const std::ios_base&)' is private
within this context
error: initializer for
'boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::phoenix::vector0<> >, 0l>::proto_child0
{aka boost::phoenix::vector0<>}' must be brace-enclosed
I am compiling these using MinGW 4.7.2 on Windows XP with Boost 1.53.0. What am I doing wrong?
Firstly, always
#include <boost/phoenix/phoenix.hpp>
unless you know what you're doing.
Secondly, you need to make either operand of operator<< be a phoenix terminal, otherwise, it will be just
std::cout << "Lambda!!"
which is an expression of type std::ostream&...
Now, you could do anything, really, e.g.
phx::ref(std::cout) << "Lambda!!"
or
std::cout << phx::val("Lambda!!")
Either will compile.