Programmer-Defined Exception Class problem - c++

I am trying to implement the code sample from a text book. It is trying to create an inherited Exception class from exception with code below.
#include <stdexcept>
#include <string>
using namespace std;
class TargetNotFoundException: public exception {
public :
TargetNotFoundException(const string& message = "")
: exception("Target not found: " + message.c_str()){ } // end constructor
}; // end TargetNotFoundException
The constructor provides a way for a throw statement to identify the condition that caused the exception. For example, the statement
throw TargetNotFoundException (target + " not found in a box!");
invokes the constructor of TargetNotFoundException. The message given to the constructor is returned by the method what that is inherited from the class exception. Thus, a catch block, such as the following one, can access the message:
catch(TargetNotFoundException except) {
cout << except.what() << endl;
}
If target has the value "glasses" when this block executes, the output is Target not found: glasses not found in a box!
However, there is a compilation error stating that:
error: invalid operands to binary expression ('const char [19]'
and 'const std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::value_type *'
(aka 'const char *'))
: exception("Target not found: " + message.c_str()){ } // end constructor
~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~

There's no + operator that takes two C strings as parameters. Simply remove .c_str() from your code
exception("Target not found: " + message){ }
Presumably just a typo from your text book.

Related

Analyzing a simple C++ program with Frama-C

I started learning C++ from a great tutorial available at https://learnxinyminutes.com/docs/c++/ and would like to analyze in Frama-C a simplest example that shows references:
using namespace std;
#include <iostream>
#include <string>
int main() {
string foo = "I am foo";
string bar = "I am bar";
string& fooRef = foo; // This creates a reference to foo.
fooRef += ". Hi!"; // Modifies foo through the reference
cout << fooRef; // Prints "I am foo. Hi!"
// Doesn't reassign "fooRef". This is the same as "foo = bar", and
// foo == "I am bar"
// after this line.
cout << &fooRef << endl; //Prints the address of foo
fooRef = bar;
cout << &fooRef << endl; //Still prints the address of foo
cout << fooRef; // Prints "I am bar"
//The address of fooRef remains the same, i.e. it is still referring to foo.
return 0;
}
I compiled and installed Frama-C C++ plug-in called "Frama-Clang".
Now when I run frama-c I get warnings and errors in the output:
$ frama-c refs.cc
[kernel] Parsing FRAMAC_SHARE/libc/__fc_builtin_for_normalization.i (no preprocessing)
[kernel] Parsing refs.cc (external front-end)
refs.cc:13:17: warning: using directive refers to implicitly-defined namespace 'std'
using namespace std;
^
In file included from refs.cc:14:
In file included from /usr/share/frama-c/frama-clang/libc++/iostream:29:
/usr/share/frama-c/frama-clang/libc++/ostream:31:40: error: implicit instantiation of undefined template 'std::basic_ios<char, std::char_traits<char> >'
class basic_ostream : virtual public basic_ios<charT,traits> {
^
refs.cc:23:7: note: in instantiation of template class 'std::basic_ostream<char, std::char_traits<char> >' requested here
cout << fooRef; // Prints "I am foo. Hi!"
^
/usr/share/frama-c/frama-clang/libc++/iosfwd:37:68: note: template is declared here
template <class charT, class traits = char_traits<charT> > class basic_ios;
^
code generation aborted due to one compilation error
[kernel] user error: Failed to parse C++ file. See Clang messages for more information
[kernel] user error: stopping on file "refs.cc" that has errors.
[kernel] Frama-C aborted: invalid user input.
What is wrong?
(Frama-C is installed from a debian-testing repository in version 20170501+phosphorus+dfsg-2)
First of all, I'd like to point out the caveat on the Frama-Clang page:
Frama-Clang is currently in an early stage of development. It is known to be incomplete and comes without any bug-freeness guarantee.
Thus, if you're not already familiar with C++, I'd kindly suggest that starting right away with Frama-Clang might be a pretty big effort.
That said, the issue is, as mentioned in the comments, that STL support in Frama-Clang is minimal (in particular, the innocent-looking iostream is not exactly the easiest piece of code to handle when it comes to templates).
You might have better luck by using frama-c -cxx-nostdinc refs.cc, which will use your system's standard library instead of the one shipped with Frama-Clang: this will at least let clang type-check your code. There is however absolutely no guarantee that Frama-Clang itself will be able to understand all the constructions provided by this library.

Absence of compilation error when using parametrized constructor

Today at work I came across a behavior in C++ which I don't understand. I have produced the following example code to illustrate my problem:
#include <string>
#include <iostream>
class MyException
{
public:
MyException(std::string s1) {std::cout << "MyException constructor, s1: " << s1 << std::endl;}
};
int main(){
const char * text = "exception text";
std::cout << "Creating MyException object using std::string(const char *)." << std::endl;
MyException my_ex(std::string(text));
std::cout << "MyException object created." << std::endl;
//throw my_ex;
std::string string_text("exception text");
std::cout << "Creating MyException object using std::string." << std::endl;
MyException my_ex2(string_text);
std::cout << "MyException object created." << std::endl;
// throw my_ex2;
return 0;
}
This code snippet compiles without any errors and produces the following output:
$ g++ main.cpp
$ ./a.out
Creating MyException object using std::string(const char *).
MyException object created.
Creating MyException object using std::string.
MyException constructor, s1: exception text
MyException object created.
Note that for my_ex the constructor I have defined was not called. Next, if I want to actually throw this variable:
throw my_ex;
I get a compilation error:
$ g++ main.cpp
/tmp/ccpWitl8.o: In function `main':
main.cpp:(.text+0x55): undefined reference to `my_ex(std::string)'
collect2: error: ld returned 1 exit status
If I add braces around the conversion, like this:
const char * text = "exception text";
std::cout << "Creating MyException object using std::string(const char *)." << std::endl;
MyException my_ex((std::string(text)));
std::cout << "MyException object created." << std::endl;
throw my_ex;
Then it works as I would have expected:
$ g++ main.cpp
$ ./a.out
Creating MyException object using std::string(const char *).
MyException constructor, s1: exception text
MyException object created.
terminate called after throwing an instance of 'MyException'
Aborted (core dumped)
I have the following questions:
Why does my first example compile? How come I don't get a compilation error?
Why doesn't the code compile, when I try to throw my_ex;?
Why do the braces resolve the problem?
According to most vexing parse, MyException my_ex(std::string(text)); is a function declaration; the function is named my_ex, taking a parameter named text with type std::string, returns MyException. It's not an object definition at all, then no constructor will be called.
Note the error message undefined reference to 'my_ex(std::string)' for throw my_ex; (you're trying to throw a function pointer in fact), which means that can't find the definition of the function my_ex.
To fix it you can add additional parentheses (as you has shown) or use braces which supported from C++11:
MyException my_ex1((std::string(text)));
MyException my_ex2{std::string(text)};
MyException my_ex3{std::string{text}};
The answer is to use {} (braced-init) as much as possible. Sometimes, though, it might be missed inadvertently. Luckily, compilers (like clang, under no extra warning flags) can hint:
warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
MyException my_ex(std::string(text));
^~~~~~~~~~~~~~~~~~~
test.cpp:13:23: note: add a pair of parentheses to declare a variable
MyException my_ex(std::string(text));
^
( )
1 warning generated.
which will immediately point you the issue.

Preprocessor ## pasting operator

What I am trying to achieve is creation of these three classes as mentioned in the code but just trying to use pre-processer in handy so that these similar classes can be created and executed rather than writing individual codes for them:
#include <iostream>
#define MYMACRO(len,baselen)
using namespace std;
class myclass ## len
{
int MYVALUE ## baselen;
public:
myclass ## len ## ()
{
cout << endl;
cout << " For class" ## len ## "'s function 'myFunction" ## len ## "' the value is: " << MYVALUE ## baselen << endl;
}
};
int main()
{
MYMACRO(10,100)
//myclass10 ob1;
MYMACRO(20,200)
//myclass20 ob2;
MYMACRO(30,300)
//myclass30 ob3;
myclass10 ob1;
myclass20 ob2;
myclass30 ob3;
cout << endl;
return 0;
}
Now I don't know whether the it can be done & since I am getting this error. If yes then please someone solve the error and enlighten me if no then please give the reason for the same so I am also reassured that we are on same page! The error is:
[root#localhost C++PractiseCode]# g++ -o structAndPreprocessor structAndPreprocessor.cpp
structAndPreprocessor.cpp:5: error: invalid token
structAndPreprocessor.cpp:6: error: invalid function declaration
structAndPreprocessor.cpp:7: error: invalid token
structAndPreprocessor.cpp:9: error: invalid token
structAndPreprocessor.cpp:9: error: invalid token
structAndPreprocessor.cpp:12: error: invalid token
structAndPreprocessor.cpp:12: error: invalid token
structAndPreprocessor.cpp:12: error: invalid token
structAndPreprocessor.cpp:12: error: invalid token
structAndPreprocessor.cpp:12: error: invalid token
structAndPreprocessor.cpp: In function `int main()':
structAndPreprocessor.cpp:25: error: `myclass10' was not declared in this scope
structAndPreprocessor.cpp:25: error: expected `;' before "ob1"
structAndPreprocessor.cpp:26: error: `myclass20' was not declared in this scope
structAndPreprocessor.cpp:26: error: expected `;' before "ob2"
structAndPreprocessor.cpp:27: error: `myclass30' was not declared in this scope
structAndPreprocessor.cpp:27: error: expected `;' before "ob3"
[root#localhost C++PractiseCode]#
You need to use \ at each end of your line to define your macro (and likely remove the using statement from the macro)
using namespace std;
#define MYMACRO(len,baselen) \
class myclass ## len \
{ \
int MYVALUE ## baselen; \
(...snip...) \
}\
};
Note the absence of escape on last line
Most likely you're doing Cpp and using Macros is discouraged. You'd better use either templates or traditional dynamic code (dpeending on your needs). Compared to macros, template bring the additional type checking at compilation and provide much more readable error messages.
The macro solution you present is a solution I've used before, but I would look at approaching this differently. The macro solution is a unwieldy and difficult to maintain and debug for all but the most trivial code.
Have you thought about generating the code you need from a template? Using Cheetah or Mako to fill out a source template would be quite a bit cleaner, and you could drive the generation from a configuration file, so you don't have to hand-maintain your list of classes.
You'd have a myclass.tmpl template file that looks something like this :
#for len, baselen in enumerate(mylist_of_classes_i_want_to_generate)
class MyClass$len
{
int MYVALUE$baselen;
public:
MyClass$len()
{
cout << endl;
cout << " For class $len's function 'myFunction $len' the value is: " << MYVALUE$baselen << endl;
}
};
#end for
You'd then call cheetah to autogenerate the code at the start of your build flow prior to compilation.

Initializing Objects and assign it to no pointer variables

I am having trouble initializing a couple of objects.I am writing a program that will perform frontier based exploration for a mobile robot using Player/Stage simulation 2.0. I have a class called Explorer. The objects I am having difficulty initializing are robot, pp, lp. I look at the reference page online, and I believe it is because there is no assignment operator for this but im hoping there is another way to do it.;
This is my header
#ifndef EXPLORER_H_
#define EXPLORER_H_
#include <libplayerc++/playerc++.h>
#include <iostream>
#include <fstream>
#include <math.h>`
#include <list>
#include "Map.h"
using namespace PlayerCc;
using namespace std;
struct Pose {
double x;
double y;
double theta;
};
struct Frontier {
int startRow;
int startCol;
int endRow;
int endCol;
double score;
};
class Explorer {
public:
Explorer();
void Explore(Map *map);
void performLaserSweep(Map *map);
void detectandgroupFrontiers(Map *map);
Frontier score_pick_Frontier();
void goToFrontier(Frontier f);
private:
PlayerClient robot;
Position2dProxy pp;
LaserProxy *lp;
Pose pose;
list<Frontier> unexploredFrontiers;
};
#endif /* EXPLORER_H_ */
this is my .cc file all that matters is the constructor so that is all i am showing
#include "Explorer.h"
Explorer::Explorer() {
robot = new PlayerClient("127.0.0.1", 6665);
pp = new Position2dProxy(robot, 0);
lp = new LaserProxy(robot, 0);
if (lp == NULL) {
cerr << "Error initializing LASER" << endl;
exit(1);
}
pp.SetMotorEnable(true);
}
Thank you in advance for the help
this is the compiler error
Explorer.cc: In constructor ‘Explorer::Explorer()’:
Explorer.cc:11: error: no matching function for call to ‘PlayerCc::Position2dProxy::Position2dProxy()’
/usr/include/player-2.0/libplayerc++/playerc++.h:1566: note: candidates are: PlayerCc::Position2dProxy::Position2dProxy(PlayerCc::PlayerClient*, uint)
/usr/include/player-2.0/libplayerc++/playerc++.h:1553: note: PlayerCc::Position2dProxy::Position2dProxy(const PlayerCc::Position2dProxy&)
Explorer.cc:13: error: base operand of ‘->’ has non-pointer type ‘PlayerCc::PlayerClient’
Explorer.cc:13: error: expected unqualified-id before ‘new’
Explorer.cc:13: error: expected ‘;’ before ‘new’
Explorer.cc:14: error: no matching function for call to ‘PlayerCc::Position2dProxy::Position2dProxy(PlayerCc::PlayerClient&, int)’
/usr/include/player-2.0/libplayerc++/playerc++.h:1566: note: candidates are: PlayerCc::Position2dProxy::Position2dProxy(PlayerCc::PlayerClient*, uint)
/usr/include/player-2.0/libplayerc++/playerc++.h:1553: note: PlayerCc::Position2dProxy::Position2dProxy(const PlayerCc::Position2dProxy&)
Explorer.cc:15: error: no matching function for call to ‘PlayerCc::LaserProxy::LaserProxy(PlayerCc::PlayerClient&, int)’
/usr/include/player-2.0/libplayerc++/playerc++.h:900: note: candidates are: PlayerCc::LaserProxy::LaserProxy(PlayerCc::PlayerClient*, uint)
/usr/include/player-2.0/libplayerc++/playerc++.h:881: note: PlayerCc::LaserProxy::LaserProxy(const PlayerCc::LaserProxy&)
make: *** [all] Error 1
robot in the Explorer class is not a pointer, but you are trying to initialize it with the new keyword:
robot = new PlayerClient("127.0.0.1", 6665); // this won't work
Same thing with the variable pp.
One of the notes on an error you're getting: note: candidates are: PlayerCc::Position2dProxy::Position2dProxy(PlayerCc::PlayerClient*, uint) also suggest that the constructor needs a PlayerClient pointer.
Try this in the Explorer class:
PlayerClient *robot;
And don't forget do delete it when you are done with it.
An easy way to spot errors like these are looking closely at the error messages. When the error says error: base operand of ‘->’ has non-pointer type it simply means that you are trying to use the pointer operator -> on something that is not a pointer.
Rather than change your class's members to pointers (which comes with its own complications), consider initializing the members rather than assigning to them. Try a Google on "c++ member initializer list" (this one result may be a good place to start: http://www.cplusplus.com/forum/articles/17820/)
From the error it tells candidates are: PlayerCc::Position2dProxy::Position2dProxy(PlayerCc::PlayerClient*, uint) but you are passing robot which is not declared as a pointer. You have declared it as PlayerClient robot; However, you are using robot as a pointer to an object.
So change that to PlayerClient *robot; and this error should be taken care off.

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.