Неправильный код C ++ 0x или ошибка компилятора? - PullRequest
6 голосов
/ 28 января 2011

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

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) и устранить возможную неоднозначность между обоими шаблонами функций-клонов путем частичного упорядочения по второму параметру функции.

К сожалению, 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 ]

1 голос
/ 28 января 2011

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

Edit : Кстати, мне сказали, что clang ++ принимает вышеуказанноекод.

1 голос
/ 28 января 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...