how can I throw a string with some variables in it?

Dec 19, 2011 at 7:28am
I have a function that does some logical error-checks on a structure I have, basically it will do a series of "if" checks and throw a string if it finds something wrong. This string is not caught, the idea is just to report the error and kill the process. I'd like to do something like this:

1
2
3
if (some_check) {
throw string("check(): Hidden node count of " + N_size_file + " exceeds maximum allowed value of " + _N_MAX);
}


I think you can see what I'm trying to do here. Obviously this doesn't work, but I would like this to basically throw this:

check(): Hidden node count of 5000 exceeds maximum allowed value of 4500


As I am writing dozens of these checks, I was hoping that I'd be able to keep it as short as possible. Performance is not an issue, as these checks are only performed during loading or in debugging situations.

Thanks in advance :)
Dec 19, 2011 at 7:35am
Assume you are using Standard C++, please see http://www.cplusplus.com/reference/std/exception/exception/

All you got to do is inherit and override/implement according the base exception class listed.

class exception {
public:
exception () throw();
exception (const exception&) throw();
exception& operator= (const exception&) throw();
virtual ~exception() throw();
virtual const char* what() const throw();
}
Dec 19, 2011 at 8:22am
Sample code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <fstream>
#include <exception>

using namespace std;

class MyException : public exception {
  private:
  string* m_ex;

  public:
  MyException(string& ex) {
    m_ex = new string(ex);
  };
  MyException(char* ex) {
    m_ex = new string(ex);
  };
  MyException(const MyException& e) throw() {
    if (e.m_ex) m_ex = new string(*(e.m_ex));
  }
  MyException& operator=(const MyException& e) throw() {
    if (e.m_ex) m_ex = new string(*(e.m_ex));
  }
  ~MyException() throw() {
    if (m_ex) delete m_ex;
  };
  const char* what() const throw() {
    return m_ex ? m_ex->c_str() : "cannot find exception string";
  }
};

int main(int argc,char** argv) {
  try {
    throw MyException("can see my exception?");
  } catch(MyException& ex) {
    cout << ex.what() << "\n";
  }
  return 0;
}
Dec 19, 2011 at 9:09am
For dynamic parameter like N_size_file which is determined at run-time, you have two options. The C style using sprintf or C++ style using ostringstream.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <sstream>
#include <exception>

using namespace std;

class MyException : public exception {
  private:
  string* m_ex;

  public:
  MyException(const string& ex) {
    m_ex = new string(ex);
  };
  MyException(const char* ex) {
    m_ex = new string(ex);
  };
  MyException(const MyException& e) throw() {
    if (e.m_ex) m_ex = new string(*(e.m_ex));
  }
  MyException& operator=(const MyException& e) throw() {
    if (e.m_ex) m_ex = new string(*(e.m_ex));
  }
  ~MyException() throw() {
    if (m_ex) delete m_ex;
  };
  const char* what() const throw() {
    return m_ex ? m_ex->c_str() : "cannot find exception string";
  }
};

int main(int argc,char** argv) {
  int N = 10;
  try {
    #ifdef C_STYLE
    char buffer[81];
    sprintf(buffer,"C: can see my own exception %d?",N);
    throw MyException(buffer);
    #else
    ostringstream oss;
    oss << "C++: can see my own exception " << N << "?";
    throw MyException(oss.str());
    #endif

  } catch(MyException& ex) {
    cout << ex.what() << "\n";
  }
  return 0;
}


PS
1. Change parameter for constructor to const to reflect the intention of the class better.
2. C++ exception base class does not mandate a no-arg constructor so I did not code it. If you want you can add to the MyException class
Last edited on Dec 19, 2011 at 9:25am
Dec 19, 2011 at 12:09pm
I would write

throw std::runtime_error("check(): Hidden node count of " + std::to_string(N_size_file) + " exceeds maximum allowed value of " + std::to_string(_N_MAX));
demo: http://ideone.com/f5zln

or

throw std::runtime_error("check(): Hidden node count of " + boost::lexical_cast<std::string>(N_size_file) + " exceeds maximum allowed value of " + boost::lexical_cast<std::string>(_N_MAX));
demo: http://ideone.com/D13J9

or

throw std::runtime_error( str(boost::format("check(): Hidden node count of %d exceeds maximum allowed value of %d ") % N_size_file % N_MAX));
demo: http://ideone.com/D29fR
Dec 19, 2011 at 12:53pm
@sohguanh: ¿why are you using dynamic allocation?
¿what if it fails?
Dec 19, 2011 at 2:45pm
Yea, wouldnt it be best to check if he tpointers are NULL after allocating new strings in case the heap memory runs out? Thats another exception. lol
Last edited on Dec 19, 2011 at 2:46pm
Dec 19, 2011 at 3:27pm
Hi I welcome all criticism. Going by argument, if heap memory can run out then so can stack memory. So does that mean if we switch to use stack memory we will be safe? Writing a bullet-proof exception class is not easy but I feel my version should suffice for most business needs unless it is very stringent memory environment. For that we should not even use exception class, we should revert back to use our traditional return int values isn't it ?
Dec 19, 2011 at 3:41pm
throw std::runtime_error("check(): Hidden node count of " + std::to_string(N_size_file) + " exceeds maximum allowed value of " + std::to_string(_N_MAX));


std::to_string(...) is there a standard C++ function called to_string ? Hmmm...
Dec 19, 2011 at 3:43pm
yes in C++11.
Dec 19, 2011 at 3:48pm
yes in C++11.


Thanks but it seems the Linux gcc compiler I have does not support C++11 yet so still need to use back stringstream class.
Dec 19, 2011 at 3:57pm
gcc 4.5 and newer has std::to_string if you activate C++11 by passing the flag -std=c++0x (or -std=c++11 in gcc 4.7) to gcc.
Dec 19, 2011 at 10:02pm
unless it is very stringent memory environment.
Maybe the trigger was a bad_alloc in the first place.
Still, the questions were unrelated. it was just a funny thought.

¿why do you unnecessary complicate your class by using dynamic allocation?
Dec 19, 2011 at 11:56pm
throw std::runtime_error("check(): Hidden node count of " + std::to_string(N_size_file) + " exceeds maximum allowed value of " + std::to_string(_N_MAX));

This is what I was after, thanks :)
Dec 20, 2011 at 1:16am
why do you unnecessary complicate your class by using dynamic allocation?

Well it could be using stack also. Possibly since long time no touch C++ (busy with Android), I want to refresh my understanding of dynamic allocation :P

In a way, the example goes to show C++ is flexible to accommodate various mode unlike Java where all objects are stored by reference so as to speak.

If you like, you can just change the class to using stack variable also. It shouldn't be so hard, in fact it will be easier.

Topic archived. No new replies allowed.