这段代码当然是愚蠢的,但是我只是写了它来说明问题。 在这里:
#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
所以我想知道为什么两个编译器在给定此代码的情况下选择调用不同的const限定转换?
如果我将get()
更改为get() const
,那么两者都会调用转换的const
版本。但是VS是否通过未标记为const
的方法调用const
转换来违反标准吗?
编辑:
为了消除对reinterpret_cast
和here's a version without it的困惑,它们仍然在两个编译器上产生相同的输出。
答案 0 :(得分:1)
方法:
template <typename T> foo::T get();
不是 const
。
这意味着对象this
在其内部是指向foo
类型的指针(而不是const foo
)。
因此,声明
this->operator T();
由于overload resolution而将其称为no-const
版本。
根据[over.match.best]
的标准规定,首选版本no-const
,因为它不需要任何 cast 。
确实,为了调用const
版本,编译器应隐式转换为const对象(即const_cast<const foo*>(this)
)。
MSVC根本不遵循此处的标准。