- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在将旧库从 VS2010 升级到 VS2017。我遇到了一个我设法修复的错误,但我不明白为什么修复有效。
下面我做了一个小测试,重现了VS2017中的错误。但是,如果您在 VS2010 中运行它,或者如果您取消注释 Date 类中的复制构造函数,则它可以正常工作。
我得到的错误:
error.cpp(115): error C2668: 'Date::Date': ambiguous call to overloaded function
error.cpp(22): note: could be 'Date::Date(Date &&)'
error.cpp(22): note: or 'Date::Date(const Date &)'
error.cpp(19): note: or 'Date::Date(std::string)'
error.cpp(18): note: or 'Date::Date(int)'
error.cpp(115): note: while trying to match the argument list '(CVariant)'
代码
#include "stdafx.h"
#include <string>
#include <memory>
class Date
{
public:
Date() { date = 19000101; }
// Copy constructor
// The code will not compile in VS2017 if this constructor is not there,
// But it compiles fine in VS2010
/*Date(const Date & dt) {
date = dt.date;
}*/
explicit Date(int yyyymmdd) { date = yyyymmdd; }
explicit Date(std::string isodate) { date = 19000101; } // Silly constructor, just for this example
private:
int date;
};
enum cvtype {
mInt,
mDate,
mNone
};
class CVariant
{
public:
CVariant() {}
// Copy constructor
CVariant(const CVariant& variant) {
copy_CVariant(variant);
}
// Copy assignment
CVariant& operator=(const CVariant& variant) {
copy_CVariant(variant);
return *this;
}
void copy_CVariant(const CVariant& variant)
{
switch (variant._type)
{
case mInt:
operator=(variant.value._Int);
break;
case mDate:
operator=(*variant.value.pDate);
break;
default:
clear();
break;
}
}
// Other constructors
CVariant(const Date& date_value) : _type(mNone) { operator=(date_value);}
CVariant(int int_value) : _type(mNone) { operator=(int_value); }
// casting
operator int() const {
if (_type == mInt) return value._Int;
else return 0;
}
operator Date() const {
if (_type == mDate) return *value.pDate;
return Date();
}
// Assignment
CVariant& operator=(int int_value) {
clear();
_type = mInt;
value._Int = int_value;
return *this;
}
CVariant& operator=(const Date& date_value) {
clear();
_type = mDate;
value.pDate = new Date(date_value);
return *this;
}
private:
void clear()
{
if (_type == mDate)
delete value.pDate;
}
union VarValue
{
int _Int;
Date* pDate;
} value;
cvtype _type;
};
int main()
{
Date t(20170516);
int i(10);
CVariant cvt(t);
CVariant cvi(i);
// The following line only works in VS2017 if
// you uncomment the copy constructor in the Date class
// This works fine in VS2010 no matter what
Date t1(cvt);
// This works
Date t2 = cvt;
Date t3 = cvi;
int i1 = cvt;
int i2 = cvi;
Date t4(cvt.operator Date());
Date t5 = cvt.operator Date();
int i3 = cvi;
return 0;
}
我相信我理解错误:当我尝试从 CVariant 创建 Date 时,有几种可能的转换,每个转换到不同的 Date 构造函数,因此调用是不明确的。
但为什么添加复制构造函数可以解决这个问题?
非常感谢您的帮助!
附言我知道使用隐式运算符转换,尤其是算术类型转换,不是一个好主意,但我的首要任务是让这个旧库进行编译。
最佳答案
由于调用不明确,带有和不带有显式复制构造函数的版本都不是有效的 C++ 代码。
碰巧 MSVC 编译器做了一些“神奇的”和非标准的事情来编译它(MSVC 的一个共同主题)。如果您尝试任何其他主要编译器(gcc、clang、icc,请参阅实例 here),它们都无法编译它。即使它“有效”,我也不会依赖这种模棱两可的代码,因为它可能(并且可能会)停止与另一个编译器版本或不同的编译器一起工作。
歧义来自 C++ 对潜在隐式转换序列进行排序的方式:它总是尝试执行最少数量的隐式转换,并且最多进行一次用户定义的转换。该标准在 [class.conv] 中更详细地描述了这个过程。 .
在您的情况下,当调用 Date t1(cvt);
时有两种方法可以解决调用,每种方法都只需要一个用户定义的转换(没有其他转换):
CVariant
的转换至 int
( CVariant::operator int()
),然后调用 Date::Date(int)
.CVariant
的转换至 Date
( CVariant::operator Date()
),然后调用(隐式)复制构造函数 Date::Date(const Date &)
.有几种方法可以解决这个问题:
explicit
关键字到 CVariant 转换之一,因此它将不再参与隐式转换。Date t1(static_cast<Date>(cvt)
使用 CVariant::operator Date()
)。CVariant
添加一个转换构造函数至 Date
( Date::Date(const CVariant &)
),这将使该构造函数不需要转换,因此编译器将更喜欢这个而不是其他两个。查看完整示例 here .
简而言之,您需要执行以下操作:
CVariant
因此在 Date
中创建转换构造函数时可以使用它的名称Date
CVariant
之后定义构造函数已定义,因此您可以使用 Cvariant
的转换至 Date
在构造函数的实现中以下是对代码的相关更改:
class CVariant;
class Date
{
public:
// [...]
explicit Date(const CVariant &cvt);
// [...]
};
class CVariant
{
// [...]
};
Date::Date(const CVariant &cvt) : Date(cvt.operator Date()) {}
关于C++ 升级到 VS2017 : error C2668 about ambiguous call,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50411219/
我几乎不敢在这里问这个问题,因为它似乎应该很容易通过谷歌或 ravendb.net 获得。但是,我一直很难找到将我的 RavenDB 升级到新版本的正确方法。我目前正在运行 573 版并希望升级到 6
这周我需要升级当前版本的 DNN。我目前使用的是 2.1.1。我不想每件事都做两次,所以,我有几个问题。 是否有升级工具或某些脚本可以帮助我进行升级。 我最好安装 4.9 还是 5.0。这是生产。 如
将 Sugarcrm 从 6.2 升级到 6.3 版本时遇到问题。当我升级本地 Sugarcrm 安装时,它可以工作,但是当我开始升级我的 Sugarcrm 6.2 站点并上传升级包时,它不会上传。
有没有办法绕过 Meteor 的自动更新功能?我坚持 Downloading meteor-tool@1.3.0_3... \ 当我尝试运行现有项目,或创建一个新项目或只是运行“
我已将应用内集成到我的 Andorid 应用程序中,用于单个产品 productone。 为此,我在我的 Google Play 控制台中创建了不同的产品 ID,如下所示: 1。 productone
我在将 TeamCity 版本 2017.1.1 升级到 2017.1.2 时遇到问题。这个问题涉及 TeamCity 和 PostgreSQL 的工作。我的工作: 停止 teamcity 进程 /e
我寻找了这个问题的具体答案,但找不到——即使是在 WAMPSERVER 网站上也是如此。我确定我忽略了它。 我有 Wampserver 2.0、MySQL 5.0.51b、PHP 5.2.6 和 Ap
我使用 Ubuntu 软件中心默认的 Eclipse 3.7。 我想将 Eclipse 升级到 kepler 版本,所以我添加了 repository 我收到以下错误消息: Cannot comple
你好 我只想安装 mercurial,但对于它需要 python 2.6 的所有版本,我尝试使用 .rpm 文件,但我唯一得到的是很多充满错误的行,它告诉我:需要安装在 2.6 之前和 2.5 之后的
我完全知道 Gradle 网站上有一些页面说明了如何升级,但仅限于 4.x 及更高版本。 我正在尝试关注 tutorial制作一个简单的“我的第一个”Minecraft 模组。在其中,您被告知安装 f
我们想升级 Kerberos(服务器和客户端) 当前:1.6.3-133.27.1 目标:1.6.3-133.49.97.1 问题是如果我们用包管理器升级它,下面会发生什么? KDC 数据库 所有主要
背景 原计划 2019 年发布的 Vue3,又经过一年的再次打磨,终于于去年 9 月正式发布。随后,不少 UI 组件库都积极参与适配,去年 12 月,Element-plus(
我有一个版本为 2.3.4 的 grails 项目,我需要尽可能升级到最新版本。查看文档我意识到从 2.x 到 3.x 有巨大的变化。 问题是:从 2 到 3、从 3 到 4、从 4 到 5 逐步升级
我正在将 API 项目从 .net5 升级到 .net6 它以前工作,现在它崩溃 内部异常消息“抛出了‘Unity.Exceptions.InvalidRegistrationException’类型
我将我的项目从 expo 44 升级到 expo 45,现在我有无数这样的错误: The module 'MaterialIcons' can't be used as JSX component.
我已经升级了掌 Helm 模板(手动) 以前的片段depoloyment.yaml : apiVersion: apps/v1beta2 kind: Deployment metadata: na
我正在尝试将我的 Scala Play Framework 应用程序升级到 2.8,这涉及将 SBT 升级到 1.x。 在我的 build.propeties 我有 sbt.version=1.3.5
我想在我的 Windows 服务器上安装 PHPUnit 3.7。我遵循了各种说明 here并以 PHPUnit 3.4.1 结束。当我尝试使用以下方法再次安装它时: pear update chan
Microsoft.Net 4.5 即将推出,我想在 MS 发布最终版本时升级我的 clickonce 应用程序。 我的问题是:已经安装了 clickonce 应用程序(使用 .net 4.0)的用户
为了将 Angular 8 更新到 9,我正在按照官方文档升级。 这建议首先更新到最新版本的 angular 8,例如: ng update @angular/core@8 @angular/cli@
我是一名优秀的程序员,十分优秀!