gpt4 book ai didi

C++ 升级到 VS2017 : error C2668 about ambiguous call

转载 作者:行者123 更新时间:2023-11-30 03:23:23 26 4
gpt4 key购买 nike

我正在将旧库从 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); 时有两种方法可以解决调用,每种方法都只需要一个用户定义的转换(没有其他转换):

  1. 来自 CVariant 的转换至 int ( CVariant::operator int() ),然后调用 Date::Date(int) .
  2. 来自 CVariant 的转换至 Date ( CVariant::operator Date() ),然后调用(隐式)复制构造函数 Date::Date(const Date &) .

解决方案

有几种方法可以解决这个问题:

  1. 添加 explicit 关键字到 CVariant 转换之一,因此它将不再参与隐式转换。
  2. 在调用站点指定您想要的转换(例如 Date t1(static_cast<Date>(cvt) 使用 CVariant::operator Date() )。
  3. CVariant 添加一个转换构造函数至 Date ( Date::Date(const CVariant &) ),这将使该构造函数不需要转换,因此编译器将更喜欢这个而不是其他两个。

如何实现选项 3

查看完整示例 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com