为什么VS和gcc在这里调用不同的转换运算符(常量与非常量)?

ada*_*603 5 c++ const operator-overloading operator-keyword

这段代码当然是愚蠢的,但是我只是为了说明问题编写了代码。这里是:

#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';
}
Run Code Online (Sandbox Code Playgroud)

使用Visual Studio 2019(ISO C ++ 17,/Ox)编译时的输出为:

T get()
operator const T*() const
42
Run Code Online (Sandbox Code Playgroud)

gcc 8.3(-std=c++17-O3)的输出为:

T get()
operator T*()
42
Run Code Online (Sandbox Code Playgroud)

所以我想知道为什么两个编译器在给定此代码的情况下选择调用不同的const限定转换?

如果我更改get()get() const,则两者都将调用const转换版本。但是VS是不是通过const未标记的方法调用转换来违反标准const

编辑:

为了消除一些混乱reinterpret_cast这里有一个没有它的版本,它仍然在两个编译器上产生相同的输出。

Bia*_*sta 1

方法:

template <typename T> foo::T get();
Run Code Online (Sandbox Code Playgroud)

不是。 const

这意味着在其体内该对象this是一个指向footype 的指针(而不是const foo)。

因此,声明

this->operator T();
Run Code Online (Sandbox Code Playgroud)

const由于重载决策,将调用无版本。

正如标准所述[over.match.best],该版本no-const是首选,因为不需要任何强制转换。事实上,为了调用该const版本,编译器应该隐式转换为 const 对象(即const_cast<const foo*>(this))。


gccclang都遵循我刚才所说的。

MSVC 根本不遵循这里的标准。