Title: using method from indirect parent
Tags: c++;language-lawyer;using-declaration
Question: Consider following code:
class user_error : public st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0runtime_error
public:
using st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what;
explicit user_error(const st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0string&amp; what_arg):st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0runtime_error(what_arg){}
class with_overriden_what : public user_error {
public:
with_overriden_what(const st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0string&amp; val) : user_error("user_error"), message(val) { }
st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0string message;
virtual const char* what() const noexcept {
return message.c_str();
with this calls:
with_overriden_what ex("thrown");
st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0cout << "1. direct result: " << ex.what() << "\n";
st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0cout << "2. sliced result: " << static_cast<user_error&gt;(ex).what() << "\n";
st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0cout << "3. ranged result: " << ex.user_error75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what() << "\n";
It is surprise for me that result of 2 and 3 is different:
1. direct result: thrown
2. sliced result: user_error
3. ranged result: st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception
Q: Is there a paragraph in standard that address this behaviour?
Comment: @R2RT http://ideone.com/QgCPXm

Comment: @user2079303 To be honest, i'm not sure. The more I think about it, the more sense my output get. But what standard says? And, as R2RT mentioned, visual produces other output.

Comment: I think case 3 is the error.  Case 2 copy constructs a new user_error object (and hence a new st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception) from the existing one, and calls it's what function -that outputs the argument passed to the original.  Case 3 calls the user_error version of what (which is actually the st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception version), and this *should* output the argument passed to the constructor - but it doesn't seem to.

Comment: @A.Lisowski Happens on cpp.sh too (once I included ``): http://cpp.sh/2y6dm.  Even happened on clang (using with rextester), so I wonder if it's a bug/feature of glibc.

Comment: @user2079303 : It's a bug in Visual Studio - *as you have explained in your answer* (the output is "implementation defined", which means "they have to define it").

Comment: The problem can be simplified to this: http://ideone.com/avu745. `what()` and `user_error75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what()` give different results even when called on a `user_error` object.

Comment: Add `override` to the override.

Comment: Which of 2 or 3 was what you expected to be the output of both?

Comment: Here is another minimal example, that demonstrates the behaviour without getting exceptions involved: http://coliru.stacked-crooked.com/a/5a9d9d259837ef6a

Comment: @MartinBonner Not a bug in glibc. More like a lack of feature that VS appears to have. I find VS behaviour quite surprising, but also potentially useful. There is probably some marginal overhead to achieve it, but if `st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what` is a bottle neck, then there is something wrong with the design :)

Comment: @MartinBonner well, if their documentation doesn't define what it is, then it is technically not conformant. Then the "bug" is in the documentation. Their official docs seem to say that the string is left unspecified. I wonder if defining something to be unspecified is sufficient for to satisfy implementation-defined requirement :) Frankly, I don't know if stdlibc++ documentation defines it either.

Comment: I've tried it in VS 2017 and my result are different (and expected):
1. direct result: thrown
2. sliced result: user_error
3. ranged result: user_error
Which compiler do you use?


Here is another answer: The difference between 2. and 3. is that 2. uses dynamic (== virtual) dispatch (== call). Dynamic dispatch is implicitly used, when a virtual function is called (see later paragraph for exception). Therefore 2. calls the most derived override, which is st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0runtime_error75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what which prints the message "user_error" that was given to the constructor, as required by the post condition of the constructor:
[runtime.error]
runtime_error(const char* what_arg);
Effects: Constructs an object of class runtime_error.
Postcondition: strcmp(what(), what_arg) == 0.
Function call using a scope resolution operator does static dispatch even if the function is virtual.
[class.virtual]
15 Explicit qualification with the scope operator (5.1) suppresses the virtual call mechanism.
Therefore overrides do not matter for 3. What matters is name resolution. The using declaration is like any other member declaration in that it hides the same name that would have otherwise been resolved from a parent.
So, user_error75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what hides st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0runtime_error75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what. And, user_error75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what is defined by st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what.
Now, what should this non virtually called st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what return according to the standard? (annotated by me):
[exception]
7 Returns: An implementation-defined NTBS. (null terminated string)
Clearly, there is no requirement to print anything in particular, such as printing a string that was passed to a constructor of a derived class that contains this as sub object. Any string is standard compliant.
A minimal example for the behaviour, that does not involve exceptions:
#include <iostream&gt;
struct A {
virtual void x() {
st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0cout << "A\n";
struct B : A {
void x() {
st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0cout << "B\n";
struct C : B {
using 75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0x;
int main() {
C c;
c.x();
c.75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0x();
return 0;
The output of the two lines must be different.
Comment for this answer: According to above, gcc (2!=3) and visual (2==3) output can be considered legal, is that correct?
Comment for this answer: Given exception definition as in question, what is the best method to extract message passed to user_error?
Comment for this answer: This simplified example does not show one thing. user_error has other what method (with parameters). In that situation using is necessary.
Comment for this answer: @user2079303 : I think you are wrong about the visual studio implementation being legal - it is *implementation defined* which means the implementation must define what it is going to be.  (And as far as I can see, they don't.)
Comment for this answer: Hmm.  The VC devs obviously don't agree with me - it *does* get your minimal example (not involving st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception) right.  They must have decided to push the variable message stuff down into st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception (and not very convoluted).
Comment for this answer: @A.Lisowski 1) Correct. It is allowed, and possible with a convoluted implementation of `st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception` to print the value given to the `str75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0runtime_error`, but not required. I added my simplified example where the output must differ  2.) `ex.runtime_error75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what()`.
Comment for this answer: (or simply remove the using declaration, which appears to be counter productive).
Comment for this answer: @A.Lisowski Then use `using st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0runtime_error75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what` instead.
Comment for this answer: Then, do what I suggested before I suggested you modify user_error: `ex.runtime_error75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what()`
Comment for this answer: @MartinBonner Yeah, not convoluted after all. It seems to be pretty trivially enabled by VS extension that adds exception message to the base class. My first guess was some internal virtual dispatch, which is what I would have described convoluted.
Comment for this answer: @user2079303 I've checked VS implementation and I guess the difference here is made by fact that `st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0runtime_error` inherits from `st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception` but does not override `what`, so `using st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0exception75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0what;` does not skip any function in inheritance chain, thus result is the same function call.

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 12, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2017:00:08/10/17', 'FavoriteCount': 0.0, 'PostTypeId': 1, 'Tags': '<c++><language-lawyer><using-declaration>', 'Title': 'using method from indirect parent', 'ViewCount': 143, 'id': 45611464, 'user_AboutMe': None, 'user_AccountId': 11258800.0, 'user_DisplayName': 'A. Lisowski', 'user_Reputation': 61.0, 'user_Views': 7.0, 'user_id': 8257709.0}}