0

I was looking at this answer and wanted to use. However, I get a segmentation fault, when using the static_cast and const_cast, but if I use a temp variable everything is fine. It is obviously because the non-const version of bar() calls it self over-and-over. But I though the static_cast would result in a const foo* and then choose the const version of bar(). Why is that so?

#include <iostream>
using namespace std;

class foo
{
    public:
    void bar() const
    {
        cout << "const" << endl;
    }

    void bar()
    {
        cout << "non-const" << endl;

//      static_cast<const decltype(this)>(this)->bar();

//      const_cast<const decltype(this)>(this)->bar();

        const auto& tmp = *this;
        tmp.bar();
    }
};

int main() {
    foo A;
    A.bar();
    const foo B;
    B.bar();
    static_cast<const foo*>(&A)->bar();
    return 0;
}
Community
  • 1
  • 1
Jonas
  • 6,915
  • 8
  • 35
  • 53

1 Answers1

5

decltype(this) is foo*. And const decltype(this) is foo* const.

You don't change the pointees cv-qualifications, only the pointers. Therefore the non-const overload is chosen every time.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 1
    Ok, that actually make sense. I guess the same thing happens if I cast it to a reference, it would then be a `foo& const` (which is nonsense) instead of a `const foo&`. – Jonas Nov 16 '16 at 08:08
  • 1
    Which also hints at what could be done instead, but could be useful to mention explicitly: `static_cast*>(this)` should work. It's long though, but it avoids what I think the OP tried to avoid: it avoids specifying the type explicitly. –  Nov 16 '16 at 08:12
  • 1
    @hvd, one can also use `static_cast::type>(this)` where the meta-function is defined something like [this](http://ideone.com/RPGzLf). Haven't thoroughly tested though. – StoryTeller - Unslander Monica Nov 16 '16 at 08:14
  • 1
    @StoryTeller your `add_const_deep` does not require C++14, which is nice for production code. – Jonas Nov 16 '16 at 08:31
  • Yet another example of why "leading `const`" is misleading. `const` applies to the part of the type on the left of where `const` is, except if you put it first, then where it applies depends on more complex rules than I can summarize in this comment, especially when you factor in aliases. `decltype(this) const` is clear; `const decltype(this)` has the same meaning. Meanwhile, if `this` is `X*`, then `X* const` and `const X*` have different meanings; the "leading `const`" changes behavior depending on if it leads an alias or not; the trailing *does not*. – Yakk - Adam Nevraumont Nov 16 '16 at 14:21