Я обновляю старую библиотеку с 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;
}
Мне кажется, что я понимаю ошибку: когда я пытаюсь создать Date из CVariant,возможно несколько преобразований, каждое в разные конструкторы Date, поэтому вызов неоднозначен.
Но почему добавление конструктора копирования решает эту проблему?
Большое спасибо за помощь!
PS Мне известно, что используются неявные операторные преобразования, особенно в арифметических типах.не очень хорошая идея, но мой первый приоритет - просто собрать эту старую библиотеку.