2015-09-06 4 views
2

Вот небольшой пример, который демонстрирует нечеткий моментСледует ли игнорировать явный конструктор копирования?

struct CL 
{ 
    CL(){} 
    CL(int){} 
    explicit CL(const CL&){} 
}; 

int main() { 
    CL cl1; 
    CL cl2=5;  //(1) 
    CL cl3=(CL)5; //(2) 
    return 0; 
} 

Класс CL есть конструктор преобразования из междунар и конструктор копирования отмечен как явный. В (1) случай 5 (int) неявно преобразован в CL, а затем cl2 инициализируется напрямую. В (2) случай cl3 инициализируется копированием. В обоих случаях должен быть задействован явный конструктор copy-constructor. Но разные компиляторы дают разные результаты:

лязг и VS: первый случай, это правильно, но второй не так
НКУ: в обоих случаях являются неправильными

Я думаю, лязг и VS правы, потому что в соответствии со стандартом «явно» ключевое слово предотвращает использование конструктора в инициализации копирования, но не в прямой инициализации, а gcc неверно, поскольку в (1) случае применяется прямая инициализация.
Кто из компиляторов прав?

+5

[Ошибка 54521] (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54521), исправлено в последнее время –

ответ

2

§ 12.3.1 [class.conv.ctor]/p2:

Явный конструктор строит объекты так же, как без явных конструкторов, но делает это только тогда, когда синтаксис прямой инициализации (8,5) или там, где явно используются броски (5.2.9, 5.4).

Пример 1:

CL cl2 = 5; 

§ 8.5 [dcl.init]/р17:

выбранная функция вызывается с выражением инициализатора в качестве его аргумента ; если функция является конструктором, вызов инициализирует временную версию cv-unqualified типа назначения. Временной является prvalue. Результат вызова (который является временным для случая конструктора) затем используется для прямого инициализации, в соответствии с приведенными выше правилами, объектом, который является местом назначения инициализации копирования.

В прямой инициализации могут быть рассмотрены конструкторы explicit, поэтому ошибки не ожидается. Компонент GCC уже компилирует этот пример successfully. Это было bug 54521.


Пример 2:

CL cl3 = (CL)5; 

В этом случае, что литой синтаксис выполняет static_cast:

§ 5.2.9 [expr.static.cast]/р4:

Выражение e может быть явно преобразовано в тип T с использованием static_cast форму static_cast<T>(e) , если декларация T t(e); является хорошо сформированной, для какой-либо изобретенной временной переменной t (8.5).Эффект такого явного преобразования совпадает с выполнением декларации и инициализации, а затем с использованием переменной в результате преобразования.

РИТ имеет тип CL, и (от копирования) требует инициализации не- explicit конструктор, таким образом, как ожидается, ошибка.

Смежные вопросы