How do I deal with warnings generated by Boost.Spirit? - c++

I have recently installed boost, and i was experimenting with the Spirit library. I compiled a simple example which parses a comma-seperated list of numbers and adds them together. The program compiled, but my compiler (VS 2013) issued a rediculous amount of warnings. Have a look at the source:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <iostream>
#include <string>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;
using qi::double_;
using qi::_1;
using ascii::space;
using phoenix::ref;
template <typename Iterator>
bool adder(Iterator first, Iterator last, double& n)
{
bool r = qi::phrase_parse(first, last,
// Begin grammar
(
double_[ref(n) = _1] >> *(',' >> double_[ref(n) += _1])
)
,
// End grammar
space);
if (first != last) // fail if we did not get a full match
return false;
return r;
}
int main()
{
std::string str;
std::getline(std::cin, str);
double result;
if (!adder(str.begin(), str.end(), result))
{
std::cout << "Invalid syntax." << std::endl;
}
std::cout << "The result is " << result << std::endl;
return 0;
}
This generated 309 lines of warnings! They all looked similar to this:
c:\boost\boost/spirit/home/support/terminal.hpp(264) : warning C4348: 'boost::spirit::terminal<boost::spirit::tag::lit>::result_helper' : redefinition of default parameter : parameter 3
c:\boost\boost/spirit/home/support/terminal.hpp(270) : see declaration of 'boost::spirit::terminal<boost::spirit::tag::lit>::result_helper'
c:\boost\boost/spirit/home/support/common_terminals.hpp(142) : see reference to class template instantiation 'boost::spirit::terminal<boost::spirit::tag::lit>' being compiled
The program compiled fine and did what I thought it would do, but I'm wondering how to manage all of these warnings without silencing the useful ones. Is there a way to disable warnings originating from boost, but to preserve the warnings generated by my code? Spirit is a fairly popular library, so I know that there's some way to deal with it.

With VC++ you need to wrap your Boost includes in a few pragmas:
#pragma warning(push)
#pragma warning(disable : 4348)
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#pragma warning(pop)
#include <iostream>
#include <string>
// ...
Add to the disable list as needed, space delimited (docs).
Other compilers typically allow you to tag specified include paths as 'system' paths, and all warnings from headers in system paths are suppressed. For GCC and Clang in particular, use -isystem rather than -I (docs).

Related

How to avoid error message: reference to "is_empty" is ambiguous

So in my code, I've used a method is_empty()in the boost library. I know is_empty has two definitions, one is in the filesystem library of boost:
std::filesystem:is_empty(const std::filesystem::path& p).
And another is in std::integral_constant:
inline constexpr bool is_empty_v = is_empty<T>::value;
I intended to use the one that is in the boost library, but how can I do it? I tried to not do using namespace std at the beginning. Instead, every time I need to cout, I'd use std::cout to avoid the possible ambiguous on my is_empty method. But I still got the same error if I do this. Is there any other way that can resolve this misconception? I attached part of my code snippet below. Thank you!
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "boost/filesystem.hpp"
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
...
using namespace boost::filesystem;
using namespace cv;
... inside main() function:
...
directory_iterator itr(param.referFolder);
if( is_empty(itr->path()) )
{
std::cout << "ERROR: ReferenceFolder is empty. Please place reference images inside." << std::endl;
return 1;
}
... ...
for(directory_iterator itr(param.dataFolder); itr != end_itr; ++itr) // search every folder
{
if(is_directory(itr->status()) && !is_empty(itr->path())){
... ...
}
}

"name followed by '::' must be a class or namespace name" error in release mode but not debug mode

C++, Visual Studio 2019
I keep getting this error in release mode but not debug mode for lines that use the "filesystem" and "chrono" libraries. I'm thinking that the issue probably relates to how the header files are linked in release mode.
Below are the relevant snippets of my code (ellipses indicate omitted code). The red underline of the error is under "chrono" and "filesystem", respectively.
#include <iostream>
#include <vector>
#include <fstream>
#include <numeric>
#include <string>
#include <algorithm>
#include <ctime>
#include <iterator>
#include <filesystem>
#include <cmath>
using namespace std;
...
int main() {
auto startTime = chrono::steady_clock::now(); // ERROR HERE
...
for (auto& entry : filesystem::directory_iterator(AbsPath + PTS_ByIndustry_Path)) { // ERROR HERE
if (find(TS_ToIncludeNums.begin(), TS_ToIncludeNums.end(), i) != TS_ToIncludeNums.end()) {
string p = entry.path().u8string();
PTS_ToInclude.push_back(p);
}
i++;
}
...
}
Fixed already! In project properties, I was changing the language standard to C++17 for Debug Mode but not Release Mode.
Screenshot:
.
It seems you didn't import the chrono header.
#include <chrono>

c++ iterate through a vector of strings

So I recently discovered the use of map and vectors, however, I'm having trouble of trying to figure a way to loop through a vector containing strings.
Here's what I've tried:
#include <string>
#include <vector>
#include <stdio>
using namespace std;
void main() {
vector<string> data={"Hello World!","Goodbye World!"};
for (vector<string>::iterator t=data.begin(); t!=data.end(); ++t) {
cout<<*t<<endl;
}
}
and when I try to compile it, I get this error:
cd C:\Users\Jason\Desktop\EXB\Win32
wmake -f C:\Users\Jason\Desktop\EXB\Win32\exbint.mk -h -e
wpp386 ..\Source\exbint.cpp -i="C:\WATCOM/h;C:\WATCOM/h/nt" -w4 -e25 -zq -od -d2 -6r -bt=nt -fo=.obj -mf -xs -xr
..\Source\exbint.cpp(59): Error! E157: col(21) left expression must be integral
..\Source\exbint.cpp(59): Note! N717: col(21) left operand type is 'std::ostream watcall (lvalue)'
..\Source\exbint.cpp(59): Note! N718: col(21) right operand type is 'std::basic_string<char,std::char_traits<char>,std::allocator<char>> (lvalue)'
Error(E42): Last command making (C:\Users\Jason\Desktop\EXB\Win32\exbint.obj) returned a bad status
Error(E02): Make execution terminated
Execution complete
I tried the same method using map and it worked. The only difference was I changed the cout line to:
cout<<t->first<<" => "<<t->last<<endl;
Add iostream header file and change stdio to cstdio.
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
using namespace std;
int main()
{
vector<string> data={"Hello World!","Goodbye World!"};
for (vector<string>::iterator t=data.begin(); t!=data.end(); ++t)
{
cout<<*t<<endl;
}
return 0;
}
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> data = {"Hello World!", "Goodbye World!"};
for (std::vector<std::string>::iterator t = data.begin(); t != data.end(); t++) {
std::cout << *t << std::endl;
}
return 0;
}
Or with C++11 (or higher):
#include <iostream>
#include <vector>
#include <string>
typedef std::vector<std::string> STRVEC;
int main()
{
STRVEC data = {"Hello World!", "Goodbye World!"};
for (auto &s: data) {
std::cout << s << std::endl;
}
return 0;
}
From the Open Watcom V2 Fork-Wiki on the C++ Library Status page:
<string>
Mostly complete. Although there are no I/O operators, all other member functions and string operations are available.
A workaround (besides implementing the << operator) would be asking the string instances for the C string:
for (vector<string>::iterator t = data.begin(); t != data.end(); ++t) {
cout << t->c_str() << endl;
}
This of course only works as long as the strings don't contain zero byte values.
When I compile your code, I get:
40234801.cpp:3:17: fatal error: stdio: No such file or directory
#include <stdio>
^
You clearly have a header called "stdio" in your include path that you haven't shown us.
If you change that line to the standard #include <iostream>, then the only reported error is that you wrote void main() instead of int main(). Fix that, and it will build and run.
In passing, note also that using namespace should be avoided.
I found a solution to my own issue. Instead of using a c_str, I used std::string and switched to using the G++ compiler instead of Open Watcom
Instead of having:
char *someString="Blah blah blah";
I instead replaced it with:
string someString="Blah blah blah";
This way is much more efficient and easier.

Bind a boost signal with phoenix bind

I am using boost spirit qi to parse inbound data then dispatch the correct functionality depending on it's content.
I am using boost::signals to manage the callbacks; my problem is that I don't seem to be able to use phoenix bind with the boost signals.
Consider the following test case:
#include <boost/signals.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <iostream>
void f(int i) {
std::cout << i << '\n';
}
int main() {
boost::signal<void(int)> sig;
sig.connect(f);
std::string s="123";
auto first=s.cbegin(), last=s.cend();
boost::spirit::qi::parse(
first, last,
(
boost::spirit::qi::int_
[
boost::phoenix::bind(sig, boost::spirit::qi::_1)
]
)
);
}
This doesn't compile, spitting out a wall of errors.
Note that if I replace the phoenix bind line with
boost::phoenix::bind(&f, boost::spirit::qi::_1)
it works as expected (however due to the larger design of the program this isn't possible).
Thanks in advance.
As noted by Igor R. in the comments, your original error was due to the fact that phoenix::bind copies its arguments by default and boost::signals are non-copyable. When you use phoenix::ref to solve that, another error emerges, this one caused by Boost.Phoenix v2's inability to find the returned type. This can also be easily solved by defining BOOST_SPIRIT_USE_PHOENIX_V3.
#include <boost/signals.hpp>
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <iostream>
void f(int i) {
std::cout << i << '\n';
}
int main() {
boost::signal<void(int)> sig;
sig.connect(f);
std::string s="123";
auto first=s.cbegin(), last=s.cend();
boost::spirit::qi::parse(
first, last,
(
boost::spirit::qi::int_
[
boost::phoenix::bind(boost::phoenix::ref(sig), boost::spirit::qi::_1)
]
)
);
}

stringstream was not declared in this scope

I'm having problem with stringstream.my visual studio nor linux g++ can understand stingstream. I've added sstream but it does'nt solve anything. I've worked with it before and really don't know what's up with it now?
#include <sstream>
#include <stdlib.h>
#include "SymbolTable.cpp"
#include "setjmp.h"
using namespace std;
jmp_buf *bfj;
int TOP , SP=3 ;
struct types{int int_val;float float_val;char char_val;bool bool_val;};
types DS[6400];
int main(){
...//some code here
label38 : stringstream s;
label39 : bfj = (jmp_buf *)"label65";
label40 : longjmp(*bfj,1);;
label41 : goto label43;
label42 : TOP=SP;
//some code here
}
I'm writing a compiler so the code is the output,that's why it may seams a bit odd.
If you include #include <sstream> then you must also reference the class by:
std::stringstream or declare using namespace std; before using it.
If you post more information we could provide more detailed help.
This code compiles fine for me under G++:
#include <sstream>
#include <stdlib.h>
#include "setjmp.h"
using namespace std;
jmp_buf *bfj;
int TOP , SP=3 ;
struct types{int int_val;float float_val;char char_val;bool bool_val;};
types DS[6400];
int main(){
label38 : stringstream s;
label39 : bfj = (jmp_buf *)"label65";
label40 : longjmp(*bfj,1);;
label41 : goto label43;
label42 : TOP=SP;
label43 : (void)0;
//some code here
}
The only difference is that I removed #include "SymbolTable.cpp", and added a label43.
So apparently, if it doesn't work for you, the problem is in some of the code you omitted. The //some code here parts or in SymbolTable.cpp
Of course, it also seems very suspicious that you're including a cpp file. That is most likely an error.