Boost's is_any_of causes compile warning? - c++

I have the following lines in my code:
std::vector<std::string> lines;
boost::split(lines, output, boost::is_any_of("\n"));
Where output is a const std::string.
When I compile, I get an error:
error: implicit conversion changes signedness: 'typename range_difference<iterator_range<const char *> >::type' (aka 'long') to 'std::size_t' (aka 'unsigned long') [-Werror,-Wsign-conversion]
std::size_t Size=::boost::distance(Range);
This originates from
boost::split(lines, output, boost::is_any_of("\n"));
^
Seems like an internal typing error in boost?
Anyone encountered this before?
Note: Compiling with gcc version 5.3.1 20160406 (Red Hat 5.3.1-6), most warning flags set and -Werror.
Note2: So as #sehe has shown, this is indeed a boost issue.
So let me change the question - Does anyone know of a workaround for this?
Thanks!

Reproduced issue
https://wandbox.org/permlink/LIf0wzUPQxrz7pik (GCC) and https://wandbox.org/permlink/BofswARbx1BpVE6H (Clang)
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string.hpp>
#include <vector>
#include <string>
int main() {
std::string output;
std::vector<std::string> lines;
boost::split(lines, output, boost::is_any_of("\n"));
}
This should be reported to the maintainers of Boost Algorithm (see the boost mailing list or https://svn.boost.org/trac10/query?status=assigned&status=new&status=reopened&component=string_algo&col=id&col=summary&col=status&col=owner&col=type&col=milestone&order=priority)

Seeing as there's no more activity around this issue I'll close this with saying that yes - this is a boost issue. It's easily reproduced with #sehe 's MCVE.
Apparently compiling boost with strict warnings and Werror flags is impossible.
As per my workaround, I had a fairly simple use-case and I've implemented my own, simple, version of split
inline std::vector<std::string> Split(const std::string &str, char delim)
{
std::vector<std::string> out;
std::stringstream ss(str);
std::string item;
while (std::getline(ss, item, delim)) {
out.push_back(item);
}
return out;
}

Related

Wrong attribute of sequence parser

I tried the following example from the spirit x3 docs
#include <string>
#include <iostream>
#include "boost/spirit/home/x3.hpp"
namespace x3 = boost::spirit::x3;
int main()
{
std::pair<double, double> p;
std::string input("1.0 2.0");
std::string::iterator input_pos = input.begin();
x3::phrase_parse(input_pos, input.end(),
x3::double_ >> x3::double_,
x3::space, p);
}
The error i get is
[...]/boost/boost-1.61.0/include/boost/spirit/home/x3/support/traits/move_to.hpp:62:18: error: no match for ‘operator=’ (operand types are ‘std::pair<double, double>’ and ‘std::remove_reference<double&>::type {aka double}’)
dest = std::move(src);
If i change p to be of type double it compiles and matches 2.0. This is obviously not my intention. I tried this with multiple version of gcc (4.9, 6.2, trunk) and boost version 1.61.0. I feel like this should be a configuration problem unless someone spots an error in the code.
Did someone experienced something similar and know where the problem lies?

Capitalize first letter of string

I am trying to capitalize the first character of a std::string, using the same method mentioned here. For example for the following program
#include <cctype>
#include <iostream>
#include <string>
int main()
{
std::string name = "foobar";
name[0] = std::toupper(name[0]);
std::cout << name;
}
I am expecting the output to be
Foobar
When I compile this online (using GCC 4.9.2) I get the correct output without any warnings. However, when I compile the same code in Visual Studio 2013, I get a warning during the assignment back from toupper
warning C4244: '=' : conversion from 'int' to 'char', possible loss of data
Is the above method valid according to the C++ standard or is the warning correct? Otherwise is this just a false warning by Visual Studio?
The warning is correct as far the types go; the type of std::toupper as defined in the standard is:
int toupper( int ch );
Mostly because it's a remnant from the dark C ages (the cctype header is a hint at that).
However, this is just a part of the story. There's another toupper residing in the locale header:
template< class charT >
charT toupper( charT ch, const locale& loc );
This one shouldn't give you any warnings. If you're not sure what locale to provide, std::locale() will give you the default one.
std::toupper comes from the C standard, not C++, and has an annoying interface in that it takes and returns an int not a char. Using static_cast<char>(std::toupper(name[0])) will suit you.
The warning is correct, compiler will implicitly cast from int to char but this might cause lost of data in some cases. To see warning under gcc you need to add -Wconversion compiler option. Which will generate:
main.cpp: In function 'int main()':
main.cpp:8:13: warning: conversion to '__gnu_cxx::__alloc_traits<std::allocator<char> >::value_type {aka char}' from 'int' may alter its value [-Wconversion]
name[0] = std::toupper(name[0]);
^
Foobar
Why it is not present when -Wall is set, read here:
https://gcc.gnu.org/wiki/NewWconversion
Why isn't Wconversion enabled by -Wall or at least by -Wextra?
Implicit conversions are very common in C. This tied with the fact
that there is no data-flow in front-ends (see next question) results
in hard to avoid warnings for perfectly working and valid code.
Wconversion is designed for a niche of uses (security audits, porting
32 bit code to 64 bit, etc.) where the programmer is willing to accept
and workaround invalid warnings. Therefore, it shouldn't be enabled if
it is not explicitly requested.

g++ invalid initialization error using boost::algorithm:string:split and std::string

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.

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.

Range For loop help: Expected initializer before ":" token

I am completely new to C++ and I am now following the C++ Primer book.
I wrote a small example about strings, here is the code:
#include <iostream>
#include <string>
#include <cctype>
using std::cin;
using std::cout;
using std::endl;
using std::string;
int main() {
string s("Hello World");
for (auto &c : s)
c = toupper(c);
cout << s << endl;
return 0;
}
I am on Linux with GCC version 4.4.6 and I tried to compile this code with:
g++ test_strings.c -std=c++0x
but got the following errors:
test_strings.c: In function 'int main()':
test_strings.c:14: error: expected initializer before ':' token
test_strings.c:19: error: expected primary-expression before 'return'
test_strings.c:19: error: expected ')' before 'return'
I copied the program from the textbook, so I though it was a misspelling but after a check and trying searching on the web and updating my gcc the error reminds. Help will be greatly appreciated, thanks in advance.
As per the C++0x/C++11 Support in GCC page, you need to be running gcc 4.6 to get the range-for feature.
The 4.6 changes page contains:
Improved experimental support for the upcoming C++0x ISO C++ standard, including support for constexpr (thanks to Gabriel Dos Reis and Jason Merrill), nullptr (thanks to Magnus Fromreide), noexcept, unrestricted unions, range-based for loops (thanks to Rodrigo Rivas Costa), opaque enum declarations (thanks also to Rodrigo), implicitly deleted functions and implicit move constructors.
Since you're running gcc 4.4.6, it's not available to you.