Почему один компилятор пытается использовать конструктор удаленной копии, когда доступен конструктор соответствующего типа - PullRequest
0 голосов
/ 12 сентября 2018

У меня есть свойство класса шаблона, которое охватывает другие типы:

template <typename T>
class Property
{
private:
    T value;
public:
    Property() = default;

    Property(const T& initialValue)
    : value(initialValue) {}
    virtual ~Property() = default;

    //Make this class non-copyable.
    Property(const Property&) = delete;
    Property& operator=(const Property&) = delete;

    virtual Property& operator=(const T& other)
    {
        value = other;
        return *this;
    }

    //... a bunch of other unimportant stuff
}

Visual Studio 15.7.6 и некоторые другие компиляторы вполне довольны

{ //function or class definition (default member initialization)    
    Property<int> prop = 5;
}

Однако,(слегка измененный для проприетарной цели компиляции) GCC 4.9.4 завершается ошибкой в ​​приведенном выше объявлении:

Error GD4849D22 use of deleted function 
'Property<T>::Property(const Property<T>&) [with T = int]' 

Похоже, что компилятор пытается создать свойство RValue, а затем использует конструктор удаленных копий вместо простого использованияконструктор, соответствующий типу.

Является ли это случаем, когда GCC слишком осторожен?

Property<int> prop(5); //explicit constructor call - valid with GCC Compiler

Property<int> myOtherProp;
myOtherProp = 5; //Also fine (obviously)

Или MSVC играет быстро и свободно и делает что-то, о чем говорит стандарт.t или нет?

К сожалению, я не могу обновить свою версию GCC.Поскольку обходной путь существует, я ищу больше «почему» это происходит, чем что-либо еще.

1 Ответ

0 голосов
/ 12 сентября 2018

Я считаю, что здесь происходит гарантированное копирование elision на работе (что является функцией C ++ 17). Объявление члена типа

struct A
{
    Property<int> prop = 5;
};

означает, что элемент будет инициализирован с помощью copy-initialization . Используя ваш конструктор преобразования, сначала будет создан временный объект Property из 5, из которого затем будет построено фактическое свойство. Поскольку Property не является подвижным, вызывается конструктор копирования, который удаляется. В то время как компилятору было разрешено исключить эту копию даже до C ++ 17 (и любой разумный компилятор, так как в основном это будет всегда), все равно требовалось применять все ограничения, такие как существование и доступность любого необходимые конструкторы, как если бы копия была сделана. C ++ 17 устраняет все это, в основном делая обязательным копирование.

Быстрый тест с лязгом здесь ; если вы переключите стандарт языка на c ++ 17, вы увидите, что он неожиданно заработает…

...