Спецификатор explicit
Материал из cppreference.com
Синтаксис
explicit
|
(1) | ||||||||
explicit ( выражение )
|
(2) | (начиная с C++20) | |||||||
| выражение | — | контекстно преобразованное константное выражение типа bool
|
1) Указывает, что конструктор или функция преобразования (начиная с C++11) или руководство по выводу (начиная с C++17) является явным, то есть его нельзя использовать для неявных преобразований и инициализации копированием.
|
2) Спецификатор
explicit можно использовать с константным выражением. Функция является явной тогда и только тогда, когда это константное выражение оценивается как true. |
(начиная с C++20) |
Спецификатор explicit может появляться только в последовательности-спецификаторов-объявления объявления конструктора или функции преобразования (начиная с C++11) в определении их класса.
Примечание
Конструктор с одним параметром не по умолчанию (до C++11), объявленный без спецификатора функции explicit, называется конструктором преобразования.
Оба конструктора (кроме копирования/перемещения) и пользовательские функции преобразования могут быть шаблонами функций; значение explicit не меняется.
|
Маркер struct S {
explicit (S)(const S&); // ошибка в C++20, OK в C++17
explicit (operator int)(); // ошибка в C++20, OK в C++17
};
|
(начиная с C++20) |
| Макрос Тестирования функциональности | Значение | Стандарт | Функциональность |
|---|---|---|---|
__cpp_conditional_explicit |
201806L |
(C++20) | explicit(bool)
|
Пример
Запустить этот код
struct A
{
A(int) { } // конструктор преобразования
A(int, int) { } // конструктор преобразования (C++11)
operator bool() const { return true; }
};
struct B
{
explicit B(int) { }
explicit B(int, int) { }
explicit operator bool() const { return true; }
};
int main()
{
A a1 = 1; // OK: инициализация копированием выбирает A::A(int)
A a2(2); // OK: прямая инициализация выбирает A::A(int)
A a3 {4, 5}; // OK: прямая инициализация списком выбирает A::A(int, int)
A a4 = {4, 5}; // OK: инициализация копированием списка выбирает A::A(int, int)
A a5 = (A)1; // OK: явное приведение выполняет static_cast
if (a1) { } // OK: A::operator bool()
bool na1 = a1; // OK: инициализация копированием выбирает A::operator bool()
bool na2 = static_cast<bool>(a1); // OK: выполняет прямую инициализацию
// B b1 = 1; // ошибка: инициализация копированием не учитывает B::B(int)
B b2(2); // OK: прямая инициализация выбирает B::B(int)
B b3 {4, 5}; // OK: прямая инициализация списком выбирает B::B(int, int)
// B b4 = {4, 5}; // ошибка: инициализация копированием списка не учитывает B::B(int,int)
B b5 = (B)1; // OK: явное приведение выполняет static_cast
if (b2) { } // OK: B::operator bool()
// bool nb1 = b2; // ошибка: инициализация копированием не учитывает B::operator bool()
bool nb2 = static_cast<bool>(b2); // OK: static_cast выполняет прямую инициализацию
[](...){}(a4, a5, na1, na2, b5, nb2); // может подавлять предупреждения о
// "неиспользуемой переменной"
}