Перегрузка оператора преобразования - неоднозначность функции

Я пытаюсь создать взаимодействие между моей библиотекой Math и некоторыми встроенными методами DirectX, создавая перегруженные операторы преобразования. В основном мои структуры должны преобразовывать себя либо в объект, либо в указатель на объект, с которым они связаны в библиотеке DirectX. Пример ниже:

//overloaded conversion operators
Vector3D::operator D3DXVECTOR3() const;
Vector3D::operator D3DXVECTOR3*() const;

Моя проблема заключается в том, что некоторые методы DirectX имеют перегрузки, которые принимают как ссылки, так и указатели, поэтому я получаю неоднозначную ошибку вызова, когда пытаюсь передать свой объект. Я хочу сделать это максимально удобным для конечного пользователя, поэтому я не хочу использовать явный метод преобразования (например, ToD3DXVECTOR3 ()) или явно вызывать оператора.

Итак, я хочу, чтобы он вел себя так:

//signature for DirectX method
//D3DXVec3Add(D3DXVECTOR3* vect1, D3DXVECTOR3* vect2) or
//D3DXVec3Add(D3DXVECTOR& vect1, D3DXVECTOR3& vect2)

Vector3D v1(1,1,1);
Vector3D v2(2,2,2);

D3DXVec3Add(v1, v2);

Вместо этого:

D3DXVec3Add(v1.toD3DXVECTOR3(), v2.toD3DXVECTOR3());

Я не уверен, что это вообще возможно, но есть ли предложения, как я могу исправить двусмысленность?

Редактировать:

Хотя я не могу полагаться только на неявные преобразования, я собираюсь согласиться с предложением, оставленным г-ном C64. Одно отличие состоит в том, что структура Vector3D не содержит объектов, в которые она может преобразовывать как переменные-члены:

struct Vector3D
{
float X;
float Y;
float Z;

...

//Implicit conversion operators
operator D3DXVECTOR3() const;
operator D3DXVECTOR3*() const;
operator DirectX::XMFLOAT3() const;
operator DirectX::XMFLOAT3*() const;
operator DirectX::XMVECTOR() const;
operator DirectX::XMVECTOR*() const;

...

//Explicit conversion methods
D3DXVECTOR3         ToD3DXVECTOR3() const;
static Vector3D     FromD3DXVECTOR3(const D3DXVECTOR3& vector);
DirectX::XMFLOAT3   ToXMFLOAT3() const;
static Vector3D     FromXMFLOAT3(const DirectX::XMFLOAT3& value);
DirectX::XMVECTOR   ToXMVECTOR() const;
static Vector3D     FromXMVECTOR(const DirectX::XMVECTOR& value);

private:

...

};

person dehersh    schedule 30.01.2013    source источник
comment
У меня возникла проблема с передачей ссылок моего объекта на метод, который принимал указатель на один из объектов DirectX (например, методы принимали D3DXVECTOR3 *). Ссылка вернула указатель на мою структуру, и она не смогла его преобразовать. Перегрузка адреса оператора также не работала, потому что у объекта есть более одного типа, в который он может конвертировать.   -  person dehersh    schedule 30.01.2013


Ответы (2)


Возможно ли для вас унаследовать свой Vector3D класс от D3DXVECTOR3? Так же, как ATL::CRect класс происходит от структуры RECT Win32 (добавляя удобные методы).

Если это невозможно или просто не подходит для вашего конкретного контекста дизайна, рассмотрите возможность предложения явных методов для преобразований, так же как std::string предлагает метод .c_str() для получения указателя const char* вместо использования неявного преобразования. Вы также можете найти этот пост в блоге интересным:

Вопросы и ответы читателя: Почему разве современные интеллектуальные указатели не конвертируются неявно в *?

Более того, я заметил, что D3DXVec3Add() < / a> просто использует указатели на экземпляры D3DXVECTOR3. Итак, если вы не можете получить свой собственный класс из D3DXVECTOR3 (как вы указали в комментарии), имеет смысл предоставить пару геттеров (как версии const, так и версии, отличные от const), например:

class Vector3D
{
public:

  ....

  // Get read-only access to wrapped D3DX vector
  const D3DXVECTOR3* Get() const
  {
      return &m_vec;
  }

  // Get read-write access to wrapped D3DX vector
  D3DXVECTOR3* Get()
  {
      return &m_vec;
  }

private:
  D3DXVECTOR3 m_vec;
};

а затем используйте их так:

Vector3D v1;
Vector3D v2;
Vector3D vSum;
D3DXVec3Add(vSum.Get(), v1.Get(), v2.Get());
person Mr.C64    schedule 30.01.2013
comment
Спасибо за ввод, на данный момент я не могу наследовать от класса DirectX, поэтому мне, вероятно, придется просто пойти с явным маршрутом метода преобразования. Если бы вы только могли установить приоритет перегруженным методам (например, если оба существуют, вызовите этот) :) - person dehersh; 30.01.2013
comment
@dehersh: Поскольку кажется, что D3DXVec3Add() использует указатели (вместо ссылок), я бы просто предоставил пару геттеров, как const, так и не const. Я отредактировал свой ответ с учетом этой информации. - person Mr.C64; 30.01.2013
comment
Спасибо еще раз за помощь. Однако структура Vector3D может преобразовывать не только в D3DXVECTOR3. Он также может конвертировать в XMVECTOR или XMFLOAT3, поэтому мне придется сделать геттеры более конкретными (GetD3DXVECTOR3, GetXMFLOAT3 и т. Д.). Если неявное преобразование неоднозначно, я буду использовать геттеры, а если нет, я буду использовать оператор преобразования. - person dehersh; 30.01.2013
comment
Я собираюсь опубликовать образец своей структуры. - person dehersh; 30.01.2013

Если вы можете скомпилировать с использованием стандарта C ++ 11, вы можете сделать преобразования explicit. См. https://stackoverflow.com/a/8239402/713961

person Matt Kline    schedule 30.01.2013
comment
Это, безусловно, сработает, но предпочтительнее неявное преобразование. - person dehersh; 30.01.2013