2015-06-20 2 views
1

У меня есть пользовательский двумерную тип точки, которая имеет оператор шаблона произнесения:шаблона оператор приведения, когда Т QPointF

struct MyPoint 
{ 
    double x, y; 

    template < typename T > 
    operator T() const 
    { 
     return T{ x, y }; 
    } 
}; 

Все отлично работает для std типов:

auto p1 = MyPoint{ 1, 2 }; 
auto p2 = static_cast< std::array< double, 2 > >(p1); 
auto p3 = static_cast< std::pair< double, double > >(p1); 

Но если я попробовать то же самое с QPointF, я получаю эту ошибку (используя г ++ v4.8):

../CppTest/main.cpp:23:42: error: call of overloaded 'QPointF(MyPoint&)' is ambiguous 
    auto p3 = static_cast<QPointF>(p1); 
             ^
../CppTest/main.cpp:23:42: note: candidates are: 
In file included from /usr/include/qt5/QtCore/QPointF:1:0, 
       from ../CppTest/main.cpp:2: 
/usr/include/qt5/QtCore/qpoint.h:270:18: note: constexpr QPointF::QPointF(const QPoint&) 
Q_DECL_CONSTEXPR inline QPointF::QPointF(const QPoint &p) : xp(p.x()), yp(p.y()) { } 
       ^
/usr/include/qt5/QtCore/qpoint.h:205:46: note: constexpr QPointF::QPointF(const QPointF&) 
class Q_CORE_EXPORT QPointF 
              ^
/usr/include/qt5/QtCore/qpoint.h:205:46: note: constexpr QPointF::QPointF(QPointF&&) 

Это похоже на то, что компилятор даже не пытается использовать оператор трансляции. Если я перейду на неявное преобразование, например:

QPointF p3 = p1; 

Это нормально работает. Он также работает, если я использую QPoint - он просто кажется QPointF, что вызывает проблемы, и я понятия не имею, почему.

ответ

3

Насколько я могу судить, проблема заключается в том, что QPointF предоставляет конструктор, который принимает QPoint. Когда вы делаете static_cast компилятор пытается вызвать QPointF(MyPoint&) и он видит два пути, чтобы создать QPointF из MyPoint:

  • Используйте конструктор, принимающий QPoint, путем преобразования MyPoint в QPoint первого
  • Используйте любого из существующие конструкторы, которые принимают QPointF путем преобразования MyPoint в QPointF.

Поскольку существует несколько вариантов, это однозначно.

Инициализация копирования работает, потому что p1 сначала преобразуется в QPointF, а затем вызывается конструктор копирования.

Обсуждаются различия между QPointF p(...) и QPointF p = ...here.

Чтобы проиллюстрировать этот момент Ниже приведен небольшой пример, который демонстрирует тот же вопрос:

#include <iostream> 

struct MyType 
{ 
    template < typename T > 
    operator T() const 
    { 
     return T{}; 
    } 
}; 

struct A 
{ 
    A() {} 
    A(const A &) {} 
}; 

struct B 
{ 
    B() {} 
    B(const A &) {} 
    B(const B &) {} 
}; 

int main() 
{ 
    auto my = MyType{}; 
    auto a1 = static_cast<A>(my); 
    //auto b1 = static_cast<B>(my); // fails 
    B b2 = my; 
} 
+0

Отличный ответ! – cmannett85

Смежные вопросы