I have an enumeration class and a corresponding input stream operator in the namespace fw::example.
#include <stdexcept>
#include <string>
#include <istream>
namespace fw {
namespace example {
enum class Booleans {
kFalse = 0,
kTrue = 1
};
std::istream& operator>>(std::istream& is, Booleans& boolean) {
std::string token;
is >> token;
if ("true" == token) {
boolean = Booleans::kTrue;
} else if ("false" == token) {
boolean = Booleans::kFalse;
} else {
throw std::invalid_argument{
"Invalid string representation for an enumerator of the Booleans class."};
}
return is;
}
} // namespace example
} // namespace fw
Then I bind a variable of that enum via Boost.Program_options in the same namespace:
// [...]
description_.add_options()(
"bool",
boost::program_options::value<Booleans>(&boolean_)
->required()
->default_value(Booleans::kFalse),
"A boolean string, either true or false.");
// [...]
But I do not want to expose the std::runtime_error to the user, instead I want
to use the proper exception from the framework, and that is boost::program_options::invalid_option_value.
Imagine a more complex scenario in which the enum class and the input stream operator are defined in a library and I am unable to modify that library.
So I tried the following (according to an answer I found on SO, which I can not find again):
namespace boost {
namespace program_options {
std::istream& operator>>(std::istream& is,
fw::example::Booleans& boolean) {
try {
return fw::example::operator>>(is, boolean);
} catch (std::invalid_argument const& kException) {
throw invalid_option_value{kException.what()};
}
}
} // namespace program_options
} // namespace boost
The whole code compiles, but the thing is, that only the free function fw::example::operator>> is called and therefore the wrong execption is propagated:
terminate called after throwing an instance of 'std::invalid_argument'
what(): Invalid string representation for an enumerator of the Booleans class.
I am looking for a solution to be able to cleanly separate the Boost.Program_options related code from the rest, but also use the appropriate exception.
I am using the following environment:
Boost v1.49
GCC v4.71 with the -std=c++11 argument.
The problem appears to be that you're (ab)using the streaming operator to do validation.
Instead, supply a Custom Validator to do the validation.
In that case you no longer have the conflict with the behaviour of operator<<.
The best you could hope for when adding a competing overload inside the program_options namespace would be that the compiler would find the overload acceptable /too/ and hence fail to compile it with "ambiguous overload"
Thanks to the user #sehe, I came up with the solution presented in this answer using standard stream operators and a Custom Validator of Boost.Program_options.
Ignoring the DRY issue (as in the source comments mentioned), the solution looks pretty clean. I also incorporated the common pitfall desribed in https://stackoverflow.com/a/5517755/891439.
Source Code using GCC v4.81 and Boost.Program_options v1.56:
#include <cstdint>
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include "boost/any.hpp"
#include "boost/program_options.hpp"
// Imagine the source code in the following namespace block is placed in an
// external library.
// The mapping between enumerators and strings violates the DRY principle, but
// that issue can be easily fixed, e. g. by using one [Boost.Bimap][4].
namespace fw {
namespace example {
enum class Booleans : std::uint8_t {
kFalse = 0,
kTrue = 1
};
std::ostream& operator<<(std::ostream& os, Booleans const& kBoolean) {
switch (kBoolean) {
case Booleans::kFalse:
os << "false";
break;
case Booleans::kTrue:
os << "true";
break;
default:
os.setstate(std::ios_base::failbit);
break;
}
return os;
}
std::istream& operator>>(std::istream& is, Booleans& boolean) {
std::string token;
is >> token;
if ("true" == token) {
boolean = Booleans::kTrue;
} else if ("false" == token) {
boolean = Booleans::kFalse;
} else {
is.setstate(std::ios_base::failbit);
}
return is;
}
} // namespace example
} // namespace fw
// The following source code is application specific code.
namespace fw {
namespace example {
void validate(boost::any& value,
std::vector<std::string> const& kValues,
fw::example::Booleans*,
int) {
boost::program_options::validators::check_first_occurrence(value);
std::string const& kStringValue{
boost::program_options::validators::get_single_string(kValues)};
std::istringstream iss{kStringValue};
Booleans real_value;
iss >> real_value;
if (!iss) {
throw boost::program_options::validation_error{
boost::program_options::validation_error::invalid_option_value};
}
value = boost::any{real_value};
}
} // namespace example
} // namespace fw
int main(int argc, char** argv) {
fw::example::Booleans boolean;
boost::program_options::variables_map variables_map;
boost::program_options::options_description options_description{
"Allowed Options"};
options_description.add_options()
("help,h", "Display the help message.")
("bool",
boost::program_options::value<fw::example::Booleans>(
&boolean)->required(),
"Set the boolean value.");
try {
boost::program_options::store(
boost::program_options::parse_command_line(argc,
argv,
options_description),
variables_map);
if (variables_map.count("help")) {
std::cout << options_description << "\n";
return 1;
}
boost::program_options::notify(variables_map);
} catch (boost::program_options::error const &kException) {
std::cerr << "Program Options Error: "
<< kException.what()
<< "\n\nSpecify -help for further information.\n";
return 2;
}
if (variables_map.count("bool")) {
std::cout << "The boolean value was set to "
<< variables_map["bool"].as<fw::example::Booleans>()
<< ".\n";
}
}
Can anyone provide further improvement suggestions?
Any general comments regarding the source code?
Related
I want my function to return a string, but only strings which are a member of a specific list/set of strings. How can I go about doing this?
You do not want to return a string, you want to return a string that has an additional restriction (being part of some predefined set).
For that you'd need a new type:
class BusinessStringWrapper {
public:
BusinessStringWrapper(std::string arg): value{arg} {
if (/* arg is not ok */) {
throw;
}
}
// you can replace that with factory method
// can also return std::optional instead of throwing if the condition is not met
// that depends on your application
std::string value() const { return value; }
private:
const std::string value;
};
And in your application you'd operate on this type, accessing value if needed.
Hoe about using a std::set<std::string>?
#include <iostream>
#include <set>
#include <string>
std::string helper(const std::string & str,
const std::set<std::string> & lst)
{
return lst.find(str) == lst.end() ? "" : str;
}
int main()
{
std::set<std::string> lst = {"alpha", "beta", "gamma"};
std::cout << "return " << helper("alpha", lst) << "\n";
std::cout << "return " << helper("zeta", lst) << "\n";
return 0;
}
Output
return alpha
return
Of course, it really depends on what your definition of does not return is.
If it means an empty string, then use the above solution. Keep your life simple.
If it means an error and the program should terminate, you may #include <cassert> and just
assert(lst.find(str) != lst.end());
If it means an exception to handle, you may try throw and catch.
If it means returning a std::string if str is in a predefined list, but a void if it's not, then you may need some tricks as described in <type_traits>.
You can do this std::map<CardType, std::string> in the example below, or use std::map<int, std::string> to associate a string with any integer. For example mp[123]="abcd"
#include <iostream>
#include <string>
#include <map>
enum CardType {
SPADE,
HEART,
CLUBS,
DIAMD
};
std::map<CardType, std::string> mp{
{CardType::SPADE, "Spade"},
{CardType::HEART, "Heart"},
{CardType::CLUBS, "Clubs"},
{CardType::DIAMD, "Diamond"}
};
int main()
{
std::cout << mp[CardType::SPADE] << std::endl;
return 0;
}
I am incredibly new to C++ and I have an assignment to create a test program for exception handling. I am having problems catching the exceptions, both those defined in the given classes and those I have defined in main. Could someone look over what I have and point out where I'm going wrong?
From the professor:
#ifndef STUDENT_H
#define STUDENT_H
#include <string>
using namespace std;
class Student
{
public:
Student();
Student(string thisStudentID);
void enroll(string thisSectionID);
private:
string studentID;
bool timeToThrow();
static int sneakyCount;
};
#endif
#include <string>
#include <iostream>
#include "Student.h"
#include "StudentException.h"
using namespace std;
// The constructor for this class accepts a Student ID
Student::Student(string thisStudentID)
{
// This first statement updates a variable used to help decide when to Throw an Exception
sneakyCount++;
// Any text will be accepted as the student ID in this implementation
if (!timeToThrow())
studentID = thisStudentID;
else
throw StudentException("Student " + thisStudentID + " has been expelled from this school");
}
// This default constructor shouldn't be used, so throwing an exception isn't so artificial, its
// the right thing to do. We will also find out if this constructor gets called at time that we don't expect.
Student::Student()
{
// This first statement updates a variable used to help decide when to Throw an Exception
sneakyCount++;
throw StudentException("Incorrect Call to Student Constructor - No Student ID Provided");
}
// This dummy function would enroll the student in a course
void Student::enroll(string thisSectionID)
{
// This first statement updates a variable used to help decide when to Throw an Exception
sneakyCount++;
if (!timeToThrow())
cout << endl << "Student: " << studentID << " is now enrolled in " << thisSectionID << endl;
else
throw StudentException("Section " + thisSectionID + " has been cancelled");
return;
}
// This is the code that helps decide when to throw an exception. You are welcome to look at it,
// but its only here to help generate unexpected exceptions. It will vary in different versions of Student
// as I play around with it.
int Student::sneakyCount = 0;
bool Student::timeToThrow()
{
if (sneakyCount == 4)
return true;
else
return false;
}
#ifndef STUDENTEXCEPTION_H
#define STUDENTEXCEPTION_H
#include <string>
using namespace std;
class StudentException
{
public:
StudentException(string thisErrorMessage);
string errorMessage();
private:
string message;
};
#endif
#include <string>
#include "StudentException.h"
using namespace std;
StudentException::StudentException(string whatWentWrong)
{
// Set the stored message within the object
// Any text will be accepted as the error message
message = whatWentWrong;
}
// Return the error message stored inside the object
string StudentException::errorMessage()
{
return message;
}
My code for the test program:
#include <iostream>
#include <string>
#include "StudentException.h"
#include "Student.h"
using namespace std;
int main()
{
char again = 'n';
do
{
try
{
Student testStudent1("S0000001");
testStudent1.enroll("CSC-160-500");
}
catch(StudentException())
{
StudentException testException1("Pre-requisites required");
cout << testException1.errorMessage();
}
cout << "Again?\n";
cin >> again;
}
while(tolower(again) == 'y');
return 0;
}
I only have the loop for easier testing as the Exception throwing is somewhat random. I only catch exceptions if I use catch(...). Any hints on what I'm doing wrong?
catch(StudentException())
{
StudentException testException1("Pre-requisites required");
cout << testException1.errorMessage();
}
That's not the way to do it. Your catch doesn't catch the actual exception, you should make it an argument :
catch(const StudentException& ex)
{
cout << ex.errorMessage();
}
catch(StudentException()) tries to catch a function type. You want
catch (StudentException& se)
(and then you can use se in the handler instead of constructing a new unrelated StudentException.)
catch(StudentException()) {
...
}
This is the wrong syntax. You need to say
catch(const StudentException& e) {
...
}
While we're here, it's usually a good idea for exceptions to inherit from one of the standard library's exception classes, for example
class StudentException : public std::runtime_error
{
public:
StudentException(const string& thisErrorMessage)
: std::runtime_error(thisErrorMessage)
{}
};
Not only does is this easier to implement, but it also provides the what() member function, which people will usually look for to find the exception message.
So here's an interesting question, How would I make something kinda like a wrapper for cout?
I want to be able to add it into a dll so I can throw it into my programs. but the basic syntax of it should be
Mything::mesage << "I'm some text" << im_an_int << someclass << mything::endl;
or
Mything::mesageandlog << "I'm going to print to console, and to a file!" << mything::endl;
I can handle most of the internal logic but as to what I should put to even do this. kinda stumped.
Possibly make a static stream member in my class called message, then have an event fire when its written too that runs it through a method?
Idk, I looked around and found something sortA similar, but as for throwing it into a dll I'm at a loss. (How to write a function wrapper for cout that allows for expressive syntax?)
because this requires me to use extern and a variable, but how would I make it static so I can just straight call it without creating a variable?
Bit of clarification, something like this:
mydll.h
#include <iostream>
namespace mynamespace {
extern struct LogMessage{};
template <typename T>
LogMessage& operator<< (LogMessage &s, const T &x) {
SetStdHandle(STD_OUTPUT_HANDLE, GetStdHandle(STD_OUTPUT_HANDLE));
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE);
std::cout << "[IF] ";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_WHITE);
//LogTimestamp(); --ill impliment this.
std::cout << x << endl;
//writeStreamToLogfile(s); --and ill handle this.
return s;
}
}
driverprogram.h
#include <mydll.h>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
mynamespace::LogMessage << "Something: << std::endl;
}
expected output:
"[IF] [00:00:00] Something
You can create a struct, that has a << operator
struct OutputThing
{
template< class T >
OutputThing &operator<<( T val )
{
std::cout<<val;
return *this;
}
};
Now whenever you want to log, you will have to instance the object.
OutputThing()<<"x ="<<x;
If you want to avoid the repeated construction and destruction of the object, you can make it a singleton.
struct OutputThingSingleton
{
static OutputThingSingleton& GetThing()
{
static OutputThingSingleton OutputThing;
return OutputThing;
}
template< class T >
OutputThingSingleton &operator<<( T val )
{
std::cout<<val;
return *this;
}
private:
OutputThingSingleton()
{};
};
So the call now looks like
OutputThingSingleton::GetThing()<<"x ="<<x;
Which you could shorten using a macro.
This will work across multiple dlls, however depending on how it is used you can have multiple instances of the singleton existing. This would work fine as long as you don't want to maintain any state in your singleton. If you do need to ensure a single instance, you can compile it in its own dll. Any other binary that uses this dll will share the single instance 'owned' by the dll.
First of all, just to give fair warning, I'm pretty sure this won't work in a DLL. You want to put it into a header (as it's shown here).
Second, it's probably a little more elaborate than you were considering. In particular, it defines a multi-output stream class that works like any other stream. Essentially any normal overload of operator<< should work fine with it.
Unlike a normal stream operator, however, the output goes to multiple streams, and each line of output (on all the streams) is preceded by a prefix (currently set to the value "[FIX]", but it just uses the content of a string, so whatever you put in that string should work. A more polished/finished implementation would probably allow you to set the prefix with something like a manipulator, but this (currently) doesn't support that.
Finally, it does some variadic template trickery, so you can specify the output files as either file names or existing ostream objects, or a combination thereof (e.g., see demo main at end).
First, the header:
#ifndef LOGGER_H_INC_
#define LOGGER_H_INC_
#include <iostream>
#include <streambuf>
#include <vector>
#include <fstream>
class logger: public std::streambuf {
public:
logger(std::streambuf* s): sbuf(s) {}
~logger() { overflow('\n'); }
private:
typedef std::basic_string<char_type> string;
int_type overflow(int_type c) {
if (traits_type::eq_int_type(traits_type::eof(), c))
return traits_type::not_eof(c);
switch (c) {
case '\n':
case '\r': {
prefix = "[FIX]";
buffer += c;
if (buffer.size() > 1)
sbuf->sputn(prefix.c_str(), prefix.size());
int_type rc = sbuf->sputn(buffer.c_str(), buffer.size());
buffer.clear();
return rc;
}
default:
buffer += c;
return c;
}
}
std::string prefix;
std::streambuf* sbuf;
string buffer;
};
namespace multi {
class buf : public std::streambuf {
std::vector<std::streambuf *> buffers;
public:
typedef std::char_traits<char> traits_type;
typedef traits_type::int_type int_type;
buf() {}
void attach(std::streambuf *s) { buffers.push_back(s); }
void attach(std::ofstream &s) { buffers.push_back(s.rdbuf()); }
int_type overflow(int_type c) {
bool eof = false;
for (std::streambuf *buf : buffers)
eof |= (buf->sputc(c) == traits_type::eof());
return eof ? traits_type::eof() : c;
}
};
class logstream : public std::ostream {
std::vector<std::ofstream *> streams;
buf outputs;
logger log;
void attach(std::ostream &s) { outputs.attach(s.rdbuf()); }
void attach(char const *name) {
std::ofstream *s = new std::ofstream(name);
streams.push_back(s);
outputs.attach(s->rdbuf());
}
template <typename T, typename...pack>
void attach(T &t, pack&...p) {
attach(t);
attach(p...);
}
public:
template <typename...pack>
logstream(pack&...p) : log(&outputs), std::ostream(&log) { attach(p...); }
~logstream() {
for (auto d : streams) {
d->close();
// Bug: crashes with g++ if delete is allowed to execute.
//delete d;
}
}
};
}
#endif
Then the demo of how to use it:
#include "logger"
int main(){
multi::logstream l(std::cout, "c:/path/log.txt");
l << "This is a prefixed string\n";
}
Obviously the header is fairly large, but the code to use it seems (at least to me) about as simple as you can hope for -- create an object, specifying where you want the output to go, just a normal stream -- except that you can specify more than one. Then write to it like you would to any other stream, and the output goes to all of the specified outputs, with each line preceded by the specified prefix.
I'm trying to implement a priority queue using a linked list, but I'm having issues with try/catch. Here are the relevant parts of the priority queue header file:
#ifndef PRIORITYQUEUELINKED_H
#define PRIORITYQUEUELINKED_H
#include "RuntimeException.h"
#include <list>
using namespace std;
template <typename E, typename C> // uses data type and some total order relation
class PriorityQueueLinked {
// code for PriorityQueueLinked
class EmptyPriorityQueueException : public RuntimeException {
public:
EmptyPriorityQueueException() :
RuntimeException("Empty priority queue") {}
};
// more code
#endif
Here is the RuntimeException header file:
#ifndef RUNTIMEEXCEPTION_H_
#define RUNTIMEEXCEPTION_H_
#include <string>
class RuntimeException {// generic run-time exception
private:
std::string errorMsg;
public:
RuntimeException(const std::string& err) { errorMsg = err; }
std::string getMessage() const { return errorMsg; }
};
inline std::ostream& operator<<(std::ostream& out, const RuntimeException& e)
{
out << e.getMessage();
return out;
}
#endif
Here is my main:
#include "PriorityQueueLinked.h"
#include "Comparator.h"
#include <iostream>
using namespace std;
int main() {
try {
PriorityQueueLinked<int,isLess> prique; // empty priority queue
prique.removeMin(); // throw EmptyPriorityQueueException
}
catch(...) {
cout << "error" << endl << endl;
}
getchar();
return 0;
}
My problem lies in not being able to configure a replacement for the "..." for catch. I've tried several things, one of them: "catch(PriorityQueueLinked < int,isLess > ::EmptyPriorityQueueException E)", but in this case it says that EmptyPriorityQueueException is not a member of PriorityQueueLinked. Any advice would be greatly appreciated.
Thanks
Try-catch supports inheritance with exception classes. catch (const RuntimeException & ex) will catch any subclass of RuntimeException, even if its private. This is the whole point of deriving exception classes.
By the way, never write using namespace std; is a header, you can never know who include it, and how. Also the standard library already has your genereal purpose exception class, and what a surprise! They also clall it runtime exception, exception it§s written like this: std::runtime_exception. You can find it in <stdexcept>.
I've a working logger class, which outputs some text into a richtextbox (Win32, C++).
Problem is, i always end up using it like this:
stringstream ss;
ss << someInt << someString;
debugLogger.log(ss.str());
instead, it would be much more convenient to use it like a stream as in:
debugLogger << someInt << someString;
Is there a better way than forwarding everything to an internal stringstream instance? If'd do this, when would i need to flush?
You need to implement operator << appropriately for your class. The general pattern looks like this:
template <typename T>
logger& operator <<(logger& log, T const& value) {
log.your_stringstream << value;
return log;
}
Notice that this deals with (non-const) references since the operation modifies your logger. Also notice that you need to return the log parameter in order for chaining to work:
log << 1 << 2 << endl;
// is the same as:
((log << 1) << 2) << endl;
If the innermost operation didn't return the current log instance, all other operations would either fail at compile-time (wrong method signature) or would be swallowed at run-time.
Overloading the insertion operator<< is not the way to go. You will have to add overloads for all the endl or any other user defined functions.
The way to go is to define your own streambuf, and to bind it into a stream. Then, you just have to use the stream.
Here are a few simple examples:
Logging In C++ by Petru Marginean, DDJ Sept 05th 2007
Rutger E.W. van Beusekom's logstream class, check also the .hpp alongside with this file
As Luc Hermitte noted, there is "Logging In C++" article which describes very neat approach to solve this problem. In a nutshell, given you have a function like the following:
void LogFunction(const std::string& str) {
// write to socket, file, console, e.t.c
std::cout << str << std::endl;
}
it is possible to write a wrapper to use it in std::cout like way:
#include <sstream>
#include <functional>
#define LOG(loggingFuntion) \
Log(loggingFuntion).GetStream()
class Log {
using LogFunctionType = std::function<void(const std::string&)>;
public:
explicit Log(LogFunctionType logFunction) : m_logFunction(std::move(logFunction)) { }
std::ostringstream& GetStream() { return m_stringStream; }
~Log() { m_logFunction(m_stringStream.str()); }
private:
std::ostringstream m_stringStream;
LogFunctionType m_logFunction;
};
int main() {
LOG(LogFunction) << "some string " << 5 << " smth";
}
(online demo)
Also, there is very nice solution provided by Stewart.
An elegant solution that also solves the flushing issues is the following:
#include <string>
#include <memory>
#include <sstream>
#include <iostream>
class Logger
{
using Stream = std::ostringstream;
using Buffer_p = std::unique_ptr<Stream, std::function<void(Stream*)>>;
public:
void log(const std::string& cmd) {
std::cout << "INFO: " << cmd << std::endl;
}
Buffer_p log() {
return Buffer_p(new Stream, [&](Stream* st) {
log(st->str());
});
}
};
#define LOG(instance) *(instance.log())
int main()
{
Logger logger;
LOG(logger) << "e.g. Log a number: " << 3;
return 0;
}
In the Logger class, override the << operator.
Click Here to know how to implement the << operator.
You can also avoid the logging statements inside the code
using Aspect Oriented programming.