Почему конструктор std :: bitset с длинным длинным аргументом без знака не помечен как явный?

Шаблон класса Стандартная библиотека std::bitset<N> имеет конструктор (C ++ 11 и далее, unsigned long аргумент перед C ++ 11)

constexpr bitset(unsigned long long) noexcept

Вопреки многим рекомендациям, этот конструктор с одним аргументом не помечен как explicit, В чем причина этого?

9

Решение

Явная конструкция

Основное возражение против explicit Конструктор заключается в том, что инициализация копирования из целых чисел без знака больше не работает

constexpr auto N = 64;
std::bitset<N> b(0xDEADC0DE);  // OK, direct initialization
std::bitset<N> b = 0xDEADC0DE; // ERROR, copy initialization cannot use explicit constructors

поскольку std::bitset<N> подразумевается как обобщение unsigned intконструктор, вероятно, был сделан неявным, чтобы облегчить адаптацию существующего кода в стиле C в стиле bit-twiddling на основе raw unsigned int, Создание конструктора explicit сломал бы много существующего кода (и добавление его теперь также сломало бы существующий код).

ОБНОВИТЬ: занимаясь стандартной археологией, я нашел N0624 с января 1995 года, который предложил добавить новое ключевое слово тогда explicit ко всем конструкторам с одним аргументом в предварительном проекте библиотеки. Это было поставлено на голосование на собрании в марте 1995 года (Остин). Как указано в N0661, unsigned long конструктор для bitset не было сделано explicit (единогласно, но без мотивации).

Смешанный режим смешивания битов

Тем не менее, даже если bitset легко инициализируется из unsigned long, в противном случае есть неполные операции по установке смешанного режима (&, | или же ^):

 constexpr auto N = 512;
std::bitset<N> b = 0xDEADC0DE; // OK
std::bitset<N> c = b & 0xFFFF; // ERROR, cannot deduce template arguments for rhs

Это можно исправить, предложив перегруженные операторы для поддержки смешанного режима смешанного режима:

 // @ from { &, |, ^ }

template<std::size_t N>
bitset<N> operator@(unsigned long long lhs, const bitset<N>& rhs)

template<std::size_t N>
bitset<N> operator@(const bitset<N>& lhs, unsigned long long rhs)

Перегруженные операторы как функции-члены

Шизофреническая природа std::bitset относительно функциональности смешанного режима также присутствует в operator== а также operator!=, Это функции-члены, которые имеют неявное преобразование в своих аргументах rhs, но не в своих аргументах lhs ( this указатель, который подлежит удержанию аргумента шаблона). Это приводит к следующему:

#include <bitset>
#include <iostream>

int main()
{
constexpr auto N = 64;
constexpr std::bitset<N> b = 0xDEADC0DE; // OK, copy initialization

std::cout << (b == 0xDEADC0DE);     // OK, implicit conversion on rhs
std::cout << (0xDEADC0DE == b);     // ERROR, no implicit conversion on lhs
}

Истоки этого поведения вытекают из предложения 1992 года N0128. Время этого предложения, которое во многом зависело от функциональности будущего std::bitset, был до шаблонов функций, имеющих нетипизированные параметры шаблона. Единственный возможный обходной путь в то время состоял в том, чтобы сделать все перегруженные операторы функциями-членами вместо функций, не являющихся членами. Это никогда не изменилось позже, когда стали доступны более продвинутые технологии шаблонов (см. Также этот вопрос& почему это может нарушить код).

4

Другие решения


По вопросам рекламы [email protected]