Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why VS and gcc call different conversion operators here (const vs non-const)?

This piece of code is dumb of course, but I only wrote it to illustrate the issue. Here it is:

#include <iostream>
using namespace std;

struct foo {
    int a = 42;

    template <typename T>
    operator T* () {
        cout << "operator T*()\n";
        return reinterpret_cast<T*>(&a);
    }

    template <typename T>
    operator const T* () const {
        cout << "operator const T*() const\n";
        return reinterpret_cast<const T*>(&a);
    }

    template <typename T>
    T get() {
        cout << "T get()\n";
        return this->operator T();
    }
};

int main() {
    foo myFoo;
    cout << *myFoo.get<const int*>() << '\n';
}

The output when compiled with Visual Studio 2019 (ISO C++17, /Ox) is:

T get()
operator const T*() const
42

The output with gcc 8.3 (-std=c++17, -O3) is:

T get()
operator T*()
42

So I'm wondering why the two compilers opt to call different const-qualified conversions given this code?

If I change get() to get() const, then both call the const version of the conversion. But isn't VS violating the standard by calling the const conversion from a method that isn't marked const?

EDIT:

To clear up some confusion around reinterpret_cast, here's a version without it which still produces the same output on both compilers.

like image 908
notadam Avatar asked Nov 06 '22 18:11

notadam


1 Answers

The method:

template <typename T> foo::T get();

is not const.

That implies inside its body the object this is a pointer to foo type (and not const foo).

Therefore, the statement

this->operator T();

is going to call the no-const version because of the overload resolution.

As the standard states on [over.match.best], the version no-const is preferred because does not require any cast. Indeed, in order to call the const version, the compiler should have implicitly cast into a const object (i.e. const_cast<const foo*>(this)).


Both gcc and clang follow what I have just said.

MSVC simply does not follow the standard here.

like image 91
BiagioF Avatar answered Nov 14 '22 23:11

BiagioF