Использование std :: shared_ptr с clang ++ и libstdc ++ - PullRequest
12 голосов
/ 01 ноября 2011

Я пытаюсь использовать std :: shared_ptr в clang ++ (clang версии 3.1 (trunk 143100)), используя libstdc ++ (4.6.1).У меня есть небольшая демонстрационная программа:

#include <memory>

int main()
{
    std::shared_ptr<int> some(new int);
    std::shared_ptr<int> other(some);
    return 0;
}

, которая может быть построена с использованием:

clang++ -std=c++0x -o main main.cpp

и выдает следующую ошибку:

main.cpp:6:23: error: call to deleted constructor of 'std::shared_ptr<int>'
    std::shared_ptr<int> other(some);
                         ^     ~~~~
/usr/include/c++/4.6/bits/shared_ptr.h:93:11: note: function has been explicitly marked
deleted here
class shared_ptr : public __shared_ptr<_Tp>

По какой-то причинеему нужен конструктор, который удаляется, потому что предоставляется конструктор перемещения (что является правильным поведением).Но почему он работает с (g ++ (Ubuntu / Linaro 4.6.1-9ubuntu3) 4.6.1.)?У кого-нибудь есть идеи, как это исправить?

Ответы [ 2 ]

20 голосов
/ 01 ноября 2011

Неявно объявленный конструктор копирования для shared_ptr удален, потому что shared_ptr имеет конструктор перемещения или оператор присваивания перемещения (или оба) для C ++ 11 12.8p7:

Если определение класса не указано явнообъявить конструктор копирования, один объявлен неявно.Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный конструктор копирования определяется как удаленный;в противном случае оно определяется как значение по умолчанию (8.4).

GCC 4.6.x не реализует это правило, которое вошло в рабочий документ C ++ 11 очень поздно в процессе, как N3203 = 10-0193 .Shared_ptr в libstdc ++ 4.6.x был верен на момент написания, но после этого C ++ 11 изменился .. Boost имел точно такую ​​же проблему с его shared_ptr, и это один из общие несовместимости между GCC и Clang.

Добавление конструктора копирования по умолчанию и оператора назначения копирования к shared_ptr решит проблему.

6 голосов
/ 01 ноября 2011

Стандартные заголовки библиотеки для gcc 4.6 кажутся неправильными в этом случае, поскольку стандарт требует следующий конструктор (§20.7.2.2.1 / 16):

shared_ptr(const shared_ptr& r) noexcept;

, который является конструктором копированиякажется, что отсутствует в реализации gcc.Реализация, которую я имею под рукой (g ++ - 4.6.0), предлагает (в bits/shared_ptr.h):

template<typename _Tp1>
shared_ptr(const shared_ptr<_Tp1>& __r)

Но не имеет надлежащего конструктора копирования (шаблонный конструктор не может использоваться компилятором какконструктор копирования).Я нахожу странным, однако, что такая ошибка возникнет с производственным компилятором ...

EDIT Я пытался выяснить, почему именно g ++ 4.6 компилирует приведенный выше код сэто собственная стандартная библиотека.Кажется, что он воспринимает конструктор template d как жизнеспособную перегрузку для создания копии, что заставило меня оглянуться назад к стандарту, чтобы убедиться, что это ошибка - у меня всегда было впечатление, что шаблон не можетиспользовался как конструктор копирования - или нет.

В стандарте C ++ 03 есть сноска 106)

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

Эта сноска не являетсяприсутствует в C ++ 11.Сноски не являются нормативными, поэтому должна быть другая цитата, поддерживающая эту заметку.Несколько параграфов ниже вы можете найти:

12.8 / 3 Объявление конструктора для класса X некорректно, если его первый параметр имеет тип (необязательно cv-квалифицированный) X илибо нет других параметров, либо все остальные параметры имеют аргументы по умолчанию. Шаблон функции-члена никогда не создается для выполнения копирования объекта класса в объект его типа.

Первая часть абзаца означает, что конструктор не может принятьтот же тип, что и аргумент (конструкторы копирования принимают ссылки, и разрешение такого конструктора вызовет неоднозначность), а также тот факт, что для него потребуется копирование в аргумент, для которого наилучшая перегрузка - при условии, что это запрещеноконструктор копирования-- будет той же функцией, которая, в свою очередь, потребует ... бесконечного цикла).

Во второй части предложения утверждается, что шаблонный конструктор не может использоваться для создания копий типа, что представляется нормативным разделом, поддерживающим сноску 106) .Теперь это было тщательно переписано в C ++ 11, чтобы заявить:

12.8 / 6 Объявление конструктора для класса X некорректно, если его первый параметр имеет тип (необязательно cv-qualified) X и либо нет других параметров, либо все остальные параметры имеют аргументы по умолчанию. Шаблон функции-члена никогда не создается для создания такой сигнатуры конструктора.

Теперь это означает, что ограничение шаблон нельзя использовать для копирования был удален и заменен менее строгим ограничением: шаблон не будет мгновенно создан для создания конструктора вида S( S ), то есть такого, который может вызвать неоднозначность с конструктором копирования.

При этомс меньшим ограничением, кажется, что шаблонный конструктор выше может фактически использоваться как copy-конструктор , поскольку генерируемая им сигнатура совместима.Это поддерживает поведение компилятора g ++ 4.6 при обработке заголовка bits/shared_ptr.h и подразумевает, что clang++ не может использовать шаблон в качестве допустимого конструктора.

Теперь следующий вопрос - соответствует ли стандартная реализация библиотеки, поставляемая с g ++ 4.6, или нет.Я не могу сказать от макушки головы.С одной стороны, отсутствует подпись конструктора, о которой я упоминал выше, поэтому вы можете утверждать, что она не соответствует требованиям.Но с другой стороны, совместимый компилятор должен подобрать шаблонный конструктор для достижения той же функциональности, и реализация будет вести себя , как если бы присутствовал этот конструктор.

...