C ++ явное интегральное пользовательское преобразование

У меня есть флаг flags witch — это просто обертка вокруг целого числа, и я хочу реализовать явное преобразование в произвольные целочисленные типы на основе правил преобразования для базового целочисленного типа.

то есть

скажем, у меня есть класс по линии (игнорируя нерелевантных членов)

class Flags {
unsigned int v;
explicit operator unsigned int() { return v; }
}

Могу ли я преобразовать в целочисленный тип, отличный от int, скажем

unsigned long long iflags = static_cast<unsigned long long>(flags);

скорее, чем

unsigned long long iflags = static_cast<unsigned int>(flags);

или мне нужно было бы явно определить оператор преобразования для каждого целочисленного типа, чтобы иметь возможность сделать это?

Обратите внимание, я использую C ++ 14

я прочел http://en.cppreference.com/w/cpp/language/cast_operator но не вижу ничего специфического для целочисленных типов, что заставляет меня думать, что мне нужно явно определить все допустимые преобразования, которых я хочу избежать. Я также был бы доволен функцией преобразования шаблонов, которая потерпит неудачу, если преобразование в целевой тип невозможно, отметив, что я знаю максимальное значение внутреннего целого числа, т.е. все биты флага включены, как макрос / константа FLAGS_MAX, если это будет полезно.

0

Решение

Тот static_cast попытка подпадает под [Expr.static.cast] / 4, который примерно говорит, что вы можете сделать static_cast<T>(e) если вы можете сделать T t(e); для некоторой придуманной переменной t (в формулировке есть какой-то забавный танец, чтобы позаботиться о гарантированной исключительности в стиле C и стиля C, который мы можем игнорировать для наших целей).

Эта инициализация контролируется [Dcl.init] /17.7, который говорит, что вы делаете разрешение перегрузки на функции преобразования Flagsс указателем на [Over.match.conv], который имеет это сказать о кандидатах:

Те неявные функции преобразования, которые не скрыты внутри
[Flags] и тип выхода [unsigned long long] или тип, который может быть
преобразован в тип [unsigned long long] через стандартное преобразование
последовательность — функции-кандидаты. Для прямой инициализации те
явные функции преобразования, которые не скрыты в [Flags] а также
тип доходности [unsigned long long] или тип, который можно преобразовать в
тип [unsigned long long] с квалификацией преобразования также
функции-кандидаты.

Ваш explicit operator unsigned int() ни один не дает unsigned long long ни тип, который может быть преобразован в него посредством преобразования квалификации (что здесь не имеет значения — это преобразование применимо только к указателю-у); следовательно, это не кандидат. Поскольку набор кандидатов пуст, разрешение перегрузки завершается неудачно, поэтому инициализация некорректна, как и static_cast,

1

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

Могу ли я преобразовать в целочисленный тип, отличный от int, скажем

unsigned long long iflags = static_cast<unsigned long long>(flags);

Нет, ты не можешь.

Вышеуказанное эквивалентно:

unsigned long long temp(flags);
unsigned long long iflags = temp;

Первая строка неверна, так как flags не может быть неявно преобразовано в unsigned long long,

Учитывая определение Flagsединственный допустимый метод C ++ для инициализации iflags это использовать:

 unsigned long long iflags = static_cast<unsigned int>(flags);

Если вы удалите explicit классификатор от оператора конвертации

class Flags {
unsigned int v;
public:
operator unsigned int() { return v; }
}

тогда вы можете использовать

unsigned long long iflags = static_cast<unsigned long long>(flags);
1

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