Ответ 1
Это можно сделать, явно удалив все остальные конструкторы.
struct Bool final
{
template<class T>
Bool(T) = delete;
Bool(bool value);
};
Я пытаюсь создать структуру оболочки bool, применяя безопасную идиому 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
Я пытался причинить себе боль, используя шаблоны, но безуспешно.
Как я могу заставить его работать?
Это можно сделать, явно удалив все остальные конструкторы.
struct Bool final
{
template<class T>
Bool(T) = delete;
Bool(bool value);
};
Добавить и явно удалить конструктор шаблона:
template <typename T>
Bool(T) = delete;
Он соответствует любому другому, кроме фактического bool
, лучше, чем другие конструкторы, и таким образом предотвращает неявное преобразование.
Если вам просто нужно:
Переменная, которая является только "истиной" или "ложной" и не может быть неявно преобразована в int/ char/pointer, тогда я бы посмотрел на использование класса enum:
enum class Bool {
False,
True,
};
Я пытаюсь создать структуру обертки bool, применяя безопасную идиому bool.
Не.
Безопасная идиома bool применима только в С++ 03 и более ранних версиях - если вы выражаете, что ваш тип "правдивый", делая что-то вроде:
struct A {
operator bool() const;
};
у вас возникли бы такие проблемы, как:
A{} + 4; // ok?!
A{} < 0; // ok?!
A{} == B{}; // ok if B also has operator bool??!
Таким образом, безопасная идиома bool была решением этой случайной проблемы неявного преобразования, используя указатели функций (конечно, указатели на функции!).
В С++ 11 у нас есть лучшее решение:
struct A {
explicit operator bool() const;
};
который делает именно то, что мы хотим. Фактически, это было буквально разработано для решения этой проблемы. И в то время как безопасная идиотка bool - довольно сложная конструкция, explicit operator bool
очень проста в использовании и просто делает правильную вещь. Для этого вам не нужна оболочка - на самом деле сложнее использовать вашу обертку, чем напрямую писать explicit operator bool
.
Кроме того, ваша оболочка накладывает на пользователя (a) неизбираемость, потому что вы сделали Bool
final и (b) добавочный элемент Bool
, который вам нужно синхронизировать, поэтому он вводит, а не решает проблемы, Подумайте, сколько еще потребуется для вас выполнить:
template <class T>
struct my_unique_ptr : Bool { ... };
против
template <class T>
struct my_unique_ptr {
T* ptr;
explicit operator bool() const { return ptr; }
};