Почему VS и gcc вызывают здесь разные операторы преобразования (const против non-const)? - PullRequest
5 голосов
/ 12 апреля 2019

Этот кусок кода, конечно, глуп, но я написал его только для иллюстрации проблемы. Вот оно:

#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';
}

Вывод при компиляции с Visual Studio 2019 (ISO C ++ 17, /Ox):

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

Выход с gcc 8.3 (-std=c++17, -O3):

T get()
operator T*()
42

Так что мне интересно, почему два компилятора решили вызывать разные константно-квалифицированные преобразования для данного кода?

Если я изменю get() на get() const, тогда оба вызовут const версию преобразования. Но не нарушает ли VS стандарт, вызывая преобразование const из метода, который не помечен const?

EDIT:

Чтобы устранить некоторую путаницу вокруг reinterpret_cast, , вот версия без нее , которая по-прежнему выдает одинаковый вывод на обоих компиляторах.

1 Ответ

1 голос
/ 12 апреля 2019

Метод:

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

это не const.

Это означает, что внутри его тела объект this является указателем на тип foo (а не const foo).

Следовательно, утверждение

this->operator T();

собирается вызвать версию no- const из-за разрешения перегрузки .

Как указано в стандарте [over.match.best], версия no-const является предпочтительной, поскольку не требует cast . Действительно, чтобы вызвать версию const, компилятор должен был неявно преобразовать объект const (т.е. const_cast<const foo*>(this)).


Оба gcc и clang следуют тому, что я только что сказал.

MSVC здесь просто не следует стандарту.

...