boolean — C ++ безопасная оболочка bool

Я пытаюсь создать бул обертка структура применения безопасная идиома.
Классическая реализация для решения этой проблемы довольно тривиальна: скелет может выглядеть примерно так:

struct Bool final
{
Bool() = default;

Bool(bool value)
: _value{value}
{}

explicit operator bool() const {
return _value;
}

private:
bool _value{false};
};

То, что я пытаюсь улучшить, это то, как Bool построен
Например, я хочу избежать неявного сужения по дизайну:

Bool b1(45); // yields warnings, but it compiles
Bool b2{3};  // not ok by standard

Я пытался поранить себя, используя шаблоны, но безуспешно.

Как я мог заставить это работать?

39

Решение

Вы можете достичь этого, явно удалив все остальные конструкторы.

struct Bool final
{
template<class T>
Bool(T) = delete;

Bool(bool value);
};
55

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

Добавьте и явно удалите конструктор шаблона:

template <typename T>
Bool(T) = delete;

Это соответствует чему-либо кроме фактического bool лучше, чем другие конструкторы, и, таким образом, предотвратит неявное преобразование.

23

Если вам просто нужно:
Переменная, которая является только «истиной» или «ложью» и не может быть неявно преобразована в int / char / pointer, тогда я бы посмотрел на использование класса enum:

enum class Bool {
False,
True,
};
18

Я пытаюсь спроектировать структуру оболочки bool, применяя идиому безопасной bool.

Не.

Идиома безопасной bool актуальна только в C ++ 03 и более ранних версиях, где, если вы выражаете свой тип как «правдивый», выполняя что-то вроде:

struct A {
operator bool() const;
};

вы столкнетесь с такими проблемами, как:

A{} + 4;    // ok?!
A{} < 0;    // ok?!
A{} == B{}; // ok if B also has operator bool??!

Таким образом, идиома безопасной bool была решением этой случайной проблемы неявного преобразования, используя указатели на функции (конечно же, указатели на функции!).

В C ++ 11 у нас есть лучше решение:

struct A {
explicit operator bool() const;
};

который делает именно так что мы хотим. На самом деле это было буквально разработан Для решения этой проблемы. И хотя идиома безопасного bool довольно сложная, explicit operator bool это супер просто в использовании и просто делает правильно. Вам не нужна обертка для нее — на самом деле использовать вашу обертку сложнее, чем написать explicit operator bool непосредственно.

Более того, ваша обертка накладывает на пользователя (а) неисключаемость, потому что вы сделали Bool окончательный и (б) дополнительный bool член, что вы должны держать в синхронизации, так что это вводит, а не решает проблемы. Подумайте, сколько еще работы вам предстоит выполнить:

template <class T>
struct my_unique_ptr : Bool { ... };

против

template <class T>
struct my_unique_ptr {
T* ptr;

explicit operator bool() const { return ptr; }
};
13
По вопросам рекламы [email protected]