Конструктор C++ для неявного преобразования типов

У меня есть эти коды:

class Type2 {
public:
  Type2(const Type1 & type);
  Type2(int);
const Type2 & operator=(const Type2 & type2);
//....
};

...
  Type1 t1(13);
  Type2 t2(4);

  t2=t1;

Как я понял, конструкторы Type2 с одним аргументом без ключевого слова explicit должны означать, что любые объекты Type1 или значения int могут быть неявно преобразованы в объекты Type2.

Но в последней строке t2=t1; MS Visual Studio выдает эту ошибку компиляции:

.... ошибка C2679: двоичный "=": не найден оператор, который принимает правый операнд типа "Type1" (или нет приемлемого преобразования)....

Похоже, что MS Visual Studio настаивает на том, чтобы t2=t1; соответствовал оператору присваивания с lhs=Type2 и rhs=Type1. Почему нельзя неявно преобразовать rhs в t2, а затем выполнить копирование с помощью оператора Type2=Type2?


person JavaMan    schedule 19.06.2011    source источник
comment
Этот код отлично компилируется для меня в VS2010.   -  person Oliver Charlesworth    schedule 19.06.2011
comment
Я знаю почему. Поскольку мой Type1 имеет оператор преобразования: class Type1 { operator Type2() };   -  person JavaMan    schedule 19.06.2011
comment
Могу ли я закрыть вопрос, на который сам нашел ответ?   -  person JavaMan    schedule 19.06.2011
comment
@JavaMan: вы можете (и должны) ответить на свой вопрос.   -  person Mat    schedule 19.06.2011
comment
@JavaMan: даже уместно пометить свой ответ как принятый, чтобы сообщить сообществу, что эта проблема теперь решена.   -  person Avada Kedavra    schedule 19.06.2011
comment
@JavaMan: я все еще думаю, что вы неправильно понимаете или Visual Studio 2010 ошибается. В примере, который вы привели в своем вопросе, в операторе преобразования отсутствует const, что устраняет двусмысленность.   -  person Omnifarious    schedule 19.06.2011


Ответы (2)


Я нашел ответ. Потому что мой Type1 получил оператор преобразования

    class Type1 {
    public:
        Type1 (int );
        operator  Type2() ;//casting to Type2

    ....
    };

Это так называемое "неявное двунаправленное преобразование".

person JavaMan    schedule 19.06.2011
comment
Интересный. Это прекрасно компилируется в GCC. - person Oliver Charlesworth; 19.06.2011
comment
Да, даже VS2010 иногда компилируется. Но я должен выяснить, когда именно. Это стандартная неоднозначная ситуация, когда компилятор не может сказать, какое преобразование следует использовать. ИМХО, они должны выдавать ошибку времени компиляции. - person JavaMan; 19.06.2011
comment
Если Type2 получил оператор присваивания для Type2=Type1, VS2010 компилируется. Кстати, причина, по которой я тестирую все это, заключается в том, что я хочу выяснить, могут ли компиляторы идентифицировать эти неоднозначные ситуации (как указано в моей книге C++) - person JavaMan; 19.06.2011
comment
@VJo: объединены фрагменты кода OP, а также тела фиктивных функций. - person Oliver Charlesworth; 19.06.2011

Этот код:

#include <iostream>

using ::std::cerr;

class Barney;

class Fred {
 public:
   Fred() { }
   Fred(const Barney &b) { cerr << "Using conversion constructor.\n"; }
};

class Barney {
 public:
   Barney() { }
   operator Fred() const { cerr << "Using conversion operator.\n"; return Fred(); }
};

int main(int argc, const char *argv[])
{
   const Barney b;
   Fred f;
   f = b;
   return 0;
}

генерирует эту ошибку в gcc 4.6:

g++ -O3 -Wall fred.cpp -o a.out
fred.cpp: In function ‘int main(int, const char**)’:
fred.cpp:23:8: error: conversion from ‘const Barney’ to ‘const Fred’ is ambiguous
fred.cpp:21:17: note: candidates are:
fred.cpp:16:4: note: Barney::operator Fred() const
fred.cpp:10:4: note: Fred::Fred(const Barney&)
fred.cpp:7:7: error:   initializing argument 1 of ‘Fred& Fred::operator=(const Fred&)’

Compilation exited abnormally with code 1 at Sun Jun 19 04:13:53

Теперь, если я удалю const после operator Fred(), он затем скомпилируется и использует конструктор преобразования. Если я также уберу const из объявления b в main, тогда он предпочтет оператор преобразования.

Все это соответствует правилам разрешения перегрузок. И gcc генерирует соответствующую ошибку неоднозначности, когда не может выбрать между оператором преобразования и конструктором преобразования.

Я заметил, что в приведенных вами примерах в операторе преобразования отсутствует const. Это означает, что никогда не будет случая, когда использование оператора преобразования или конструктора преобразования будет неоднозначным.

person Omnifarious    schedule 19.06.2011