Когда использовать явный спецификатор для конструкторов с несколькими аргументами?

Недавно я узнал о спецификаторе explicit.

Предположим, у нас есть:

f( W, W, W );

Теперь, если мы сделаем

f( 42, 3.14, "seven" );

Компилятор попытается выполнить следующие неявные преобразования:

f( W(42), W(3.14), W("seven") );

Если мы определили соответствующие конструкторы для W, а именно:

W(int);
W(double);
W(std::string);

... это удастся.

Однако, если мы сделаем первый явным:

explicit W(int);

... это отключает неявное преобразование.

Теперь вам нужно было бы написать:

f( W(42), 3.14, "seven" );

т. е. вынуждает вас явно указать преобразование

Теперь вопрос:

Можно написать:

explicit W(int,int); // 2 arguments!

Это компилируется!

Но я не вижу никакого соответствующего сценария, для которого может потребоваться этот синтаксис.

Может ли кто-нибудь привести минимальный пример?


person P i    schedule 25.12.2014    source источник
comment
Частично это может быть сделано только ради согласованности, поскольку многопараметрические функции также могут иметь значения по умолчанию, например. explicit W(int,int=0);.   -  person Rufflewind    schedule 25.12.2014


Ответы (1)


Если ваш конструктор является явным, а класс не предоставляет неявный конструктор, принимающий initializer_list<T>, вы не можете копировать-список-инициализировать экземпляр.

W w = {1,2}; // compiles without explicit, but not with

Простой пример

#include <iostream>

class A
{
public:
   explicit A(int, int) {}
};

class B
{
public:
    B(int, int) {}
};

int main()
{
   B b = {1,2};
   A a = {1,2};
}

Цитаты из стандарта:

8.5/16

— Если инициализатором является (не заключенный в скобки) список-инициализации в фигурных скобках, объект или ссылка инициализируются списком (8.5.4).

8.5.4/3

Список-инициализация объекта или ссылки типа T определяется следующим образом: ...

В противном случае, если T является типом класса, рассматриваются конструкторы. Перечисляются применимые конструкторы, и лучший из них выбирается с помощью разрешения перегрузки (13.3, 13.3.1.7). Если для преобразования какого-либо из аргументов требуется сужающее преобразование (см. ниже), программа некорректна.

person ForEveR    schedule 25.12.2014
comment
Перефразируя мой предыдущий комментарий: возможно, упоминание initializer_list делает ответ запутанным. Но я думаю, что это правильно. - person juanchopanza; 25.12.2014
comment
Когда вы говорите о неявном конструкторе, вы имеете в виду конструктор, не объявленный с помощью ключевого слова explicit, и это имеет смысл, но когда я читаю это, я думаю о неявно сгенерированных конструкторах, которые не объявлены пользователем. (В вашем примере, например, конструктор копирования A.) Я не знаю, является ли неявный конструктор общепринятым термином, как вы его используете, но я не встречал его раньше. - person ; 25.12.2014