c++ - 为什么 VS 和 gcc 在这里调用不同的转换运算符(const vs non-const)?
问题描述
这段代码当然是愚蠢的,但我写它只是为了说明问题。这里是:
#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
,这里有一个没有它的版本,它仍然在两个编译器上产生相同的输出。
解决方案
方法:
template <typename T> foo::T get();
不是。_ const
这意味着在其主体内部,对象this
是指向foo
类型(而不是const foo
)的指针。
因此,声明
this->operator T();
const
由于重载决议,将调用 no-版本。
正如标准所述[over.match.best]
,该版本no-const
是首选,因为不需要任何演员表。实际上,为了调用const
版本,编译器应该隐式转换为一个 const 对象(即const_cast<const foo*>(this)
)。
MSVC 根本不遵循这里的标准。
推荐阅读
- sublimetext3 - 使 Sublime Text 书签列不敏感
- c# - 用于移动和碰撞对象的性能更好的四叉树
- python - 转变
到'0'和'1' python的字符串 - java - 如果页面上存在该元素,如何出现在控制台中
- java - 如何在后台以特定间隔重复执行java文件?
- c# - 如何在我的代码中实现“if (TargetToFind != null)”以修复“Missing Reference Exception: error message
- angular - 如何在 PDFMake 中使用 Cordova 相机图片?
- api - 谷歌物联网谷歌云平台控制台中的“创建注册表”按钮在哪里?
- xslt-2.0 - 如何使用 xsl 为带有嵌套标签的父标签
- git - “git reset --hard”命令不会删除不必要的提交