Плохо образованный C ++ 0x код или ошибка компилятора?

StackOverflow https://stackoverflow.com/questions/4827531

  •  26-10-2019
  •  | 
  •  

Вопрос

В следующем коде C ++ 0x я попытался клонировать объект, используя функцию члена клона (если он существует) и вернувшись на конструктор копии:

struct use_copy_ctor {};
struct prefer_clone_func : use_copy_ctor {};

template<class T>
auto clone(T const* ptr, prefer_clone_func)
-> decltype(ptr->clone())
{ return ptr->clone(); }

template<class T>
auto clone(T const* ptr, use_copy_ctor)
-> decltype(new T(*ptr))
{ return new T(*ptr); }

struct abc {
  virtual ~abc() {}
  virtual abc* clone() const =0;
};

struct derived : abc
{
  derived* clone() const { return new derived(*this); }
};

int main()
{
  derived d;
  abc* p = &d;
  abc* q = clone(p,prefer_clone_func());
  delete q;
}

Идея состоит в том, чтобы использовать Auto ...-> Decltype (Expr) для отсеивания плохо сформированных выражений как часть вычета аргумента шаблона (SFINAE) и для разрешения возможной двусмысленности между обоими шаблонами функции клонов через частичное упорядочение WRT второй функции параметр.

К сожалению, GCC 4.5.1 не принимает эту программу:

test.cpp: In function 'int main()':
test.cpp:28:39: error: cannot allocate an object of abstract type
  'abc'
test.cpp:14:12: note:   because the following virtual functions are
  pure within 'abc':
test.cpp:16:16: note:        virtual abc* abc::clone() const
test.cpp:28:39: error: cannot allocate an object of abstract type
  'abc'
test.cpp:14:12: note:   since type 'abc' has pure virtual functions

Теперь вопрос в том, это ошибка компилятора или я был неправ, если предположить, что Sfinae применяется сюда? Я бы признателен ответ с четкими рассуждениями.

Редактировать:Если я изменюсь decltype(new T(*ptr)) к T* Код компилируется из -за разрешения перегрузки, предпочитающего первую шаблон функции в этом случае. Но это побеждает цель того, чтобы выражение как часть объявления функции. Цель состоит в том, чтобы компилятор выгнал функцию из установленного разрешения перегрузки в случае ошибки.

Это было полезно?

Решение 2

Я думаю, что убедил себя, что это на самом деле ошибка компилятора и подал отчет. Анкет Давай посмотрим что происходит. Как обходной путь decltype(new T(*ptr)) можно заменить на T*. Анкет Единственное отличие состоит в том, что шаблон функций останется частью набора разрешения перегрузки, что не является большой проблемой в этом случае.

Редактировать: Кстати, мне сказали, что Clang ++ принимает приведенный выше код.

Другие советы

У меня была очень похожая проблема с MSVC, и выяснилось, что компилятор не узнает мои совместные типы возврата в виртуальной функции. Попробуйте измениться derivedОпределение клона к возвращению abc.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top