Я недавно узнал о 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!
Это компилируется!
Но я не вижу никакого соответствующего сценария, который мог бы потребовать этот синтаксис.
Кто-нибудь может привести минимальный пример?
Если ваш конструктор является явным, и класс не предоставляет неявный конструктор, принимающий 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). Если сужение
преобразование (см. ниже) требуется для преобразования любого из аргументов,
программа плохо сформирована.