3

We would like to have a own definition of std::runtime_error:runtime_error(const string& arg). We implement such constructor in terms of the other constructor, i.e., std::runtime_error:runtime_error(const char*), like:

namespace std {
  runtime_error::runtime_error(const string& arg)
    : runtime_error(arg.c_str()) {
    ...
  }
}

With gcc-4.9.1, this is not possible, since the constructor std::runtime_error::runtime_error(const string& arg) does not exist. In gcc/4.9.1/include/c++/4.9.1/stdexcept, we see the following:

...
class runtime_error : public exception 
{
  string _M_msg;
  public:
  /** Takes a character string describing the error.  */
  explicit 
  runtime_error(const string& __arg);
  virtual ~runtime_error() _GLIBCXX_USE_NOEXCEPT;
  /** Returns a C-style character string describing the general cause of
  *  the current error (the same string passed to the ctor).  */
  virtual const char* 
  what() const _GLIBCXX_USE_NOEXCEPT;
};
...

The standard clearly says that there should be an explicit runtime_error(const char*) constructor.

19.2.6 Class runtime_error [runtime.error]

namespace std {
class runtime_error : public exception {
public:
explicit runtime_error(const string& what_arg);
explicit runtime_error(const char* what_arg);
};
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Harald
  • 240
  • 2
  • 10
  • 5
    "*We implement such constructor in terms of the other constructor*" Why would you want to? The one taking a `std::string` has a length built into it, while the other one has to do a `strlen` to compute the length. That's just a pointless waste of time. Also, you're not allowed to rewrite classes in the standard library. – Nicol Bolas Sep 22 '16 at 14:57
  • Are you using `-std=c++11`? – Fred Larson Sep 22 '16 at 14:58
  • @FredLarson Should be the default. – πάντα ῥεῖ Sep 22 '16 at 15:01
  • 1
    Just try it: doesn't compile (with -std=c++11) until [gcc 4.9.4](https://godbolt.org/g/1ZDBeU), works from [gcc 5.1](https://godbolt.org/g/lhJqpU) and from [clang 3.5](https://godbolt.org/g/OwsZw1) – Garf365 Sep 22 '16 at 15:03
  • 1
    @NicolBolas, Not allowed by compiler? I thought all namespaces were "open". Is there something some mechanism using which the compiler closes the namespaces (like packages in Java)? – blackpen Sep 22 '16 at 15:04
  • 1
    @blackpen Unless specified it is UB to add anything to the `std` namespace. – NathanOliver Sep 22 '16 at 15:05
  • 3
    @blackpen Not allowed by the C++ standard because `namespace std` (and, as of C++17, `namespace std[someNumber]`) are special. – Baum mit Augen Sep 22 '16 at 15:05
  • @BaummitAugen, Got you. – blackpen Sep 22 '16 at 15:07
  • 4
    @πάνταῥεῖ c++11 is not on by default in 4.9. – NathanOliver Sep 22 '16 at 15:10
  • 1
    @πάνταῥεῖ: Looks like c++98 is the default standard [until 6.1](https://gcc.gnu.org/projects/cxx-status.html#cxx11). – Fred Larson Sep 22 '16 at 15:16
  • 3
    It seems pointless to argue about standard compliance when the behavior of the entire program is undefined. – T.C. Sep 22 '16 at 17:23
  • @FredLarson Since one constructor is calling another constructor, C++11 is implied. Constructor delegating is simply not allowed before C++11. – Blue Demon Sep 23 '16 at 08:27
  • @T.C. Different types of UB can be more or less safe, right? So, exactly how dangerous is this "undefined behaviour"? – Blue Demon Sep 23 '16 at 08:57
  • @BlueDemon: No undefined behaviour is safe per the standard. Implementation defined behaviour does what is specified by a specific implementation, but the behaviour is still outside of the standard itself. – rubenvb Sep 23 '16 at 11:00
  • @rubenvb Appreciate the set theory lesson (!std && gcc = still outside std), but I was more interested in knowing how dangerous this UB is. An elaboration on that would actually be helpful. – Blue Demon Sep 23 '16 at 12:21
  • @Blue Undefined behaviour is just that: undefined. In the worst case your program opens a gateway to hell. More likely, your program doesn't do what you think, which is dangerous because you don't immediately see this. Even more likely, your program crashes, but not at the point of undefined behaviour. – rubenvb Sep 23 '16 at 14:59

1 Answers1

2

Perhaps this does not answer your original question, but if the intention really is to intercept the runtime_error instantiation, you can do like this (asuming gcc is used):

namespace std {
  runtime_error::runtime_error(const string& arg)
  #if (__GNUC__ > 4)
    : runtime_error(arg.c_str())
  #else
    : _M_msg(arg)
  #endif
  {
    // intercept here!
  }
}

Hopefully, the invoked runtime_error(const char*) will not be implemented in the future in terms of runtime_error(const string&), which would break all your hope and desire. =)

Blue Demon
  • 293
  • 3
  • 12