Можно ли выбросить объекты с частными конструкторами копирования?

Я столкнулся с проблемой исключения, которая мне непонятна. В С++, когда объект бросается, он сначала копируется во временный объект, а затем временный объект передается в код catch. Копия включает использование конструктора экземпляров класса объектов. AFAIK, это означает, что если класс имеет частный конструктор копирования, он не может использоваться как исключение. Однако в VS2010 следующий код компилируется и запускается:

class Except
{
    Except(const Except& other) { i = 2; }
public:
    int i;
    Except() : i(1) {}
};

int main()
{
    try
    {
        Except ex1;
        throw ex1;          // private copy constructor is invoked
    }
    catch (Except& ex2)
    {
        assert(ex2.i == 2); // assert doesn't yell - ex2.i is indeed 2
    }
    return 0;
}

Является ли это законным?

Ответ 1

Это не легально. Стандарт 15.1/5

Если использование временного объекта можно устранить без изменения значение программы, за исключением выполнения конструкторов и деструкторы, связанные с использованием временного объекта (12.2), то исключение в обработчике можно инициализировать напрямую с аргументом выражения throw. Когда брошенный объект является объект класса и конструктор копирования, используемый для инициализации временная копия недоступна, программа плохо сформирована (даже если временный объект в противном случае можно было бы исключить). Аналогично, если деструктор для этого объекта недоступен, программа (даже если временным объектом в противном случае может быть устранена).

Ответ 2

Нет, это не так.

15.1.5 Когда брошенный объект является объектом класса, конструктор copy/move и деструктор должны быть доступны, даже если операция копирования/перемещения завершена