#c #type-conversion #operator-overloading #idioms
#c #тип-преобразование #оператор-перегрузка #идиомы
Вопрос:
Предположим, что существует шаблонный класс template <class T> myclass;
.
Существует ли идиоматический способ разрешить преобразование объектов из неконстантных T
в объекты из const T
?
В принципе, я хочу, чтобы следующее преобразование выполнялось неявно:
void f(myclass<const int> x);
myclass<int> a;
f(a); // should compile
ВАЖНОЕ РЕДАКТИРОВАНИЕ:
Похоже, что ответ очень тривиален (и вопрос довольно глупый), но в нем есть что-то очень концептуальное (по крайней мере, для меня).
У меня создалось впечатление, что мне нужно условно включить оператор преобразования, потому что оператор преобразования из myclass<const T>
в myclass<const T>
не имеет никакого смысла, т. Е. Мне нужно объявить оператор преобразования тогда и только тогда T
, когда он был const
указан. Я ожидал, что компилятор пожалуется на избыточный оператор преобразования.
Теперь, учитывая, что компилятор доволен оператором преобразования идентификаторов, который преобразует тип X
в X
, в чем разница между оператором присваивания или конструктором копирования и оператором преобразования идентификаторов?
MSVC выдает предупреждение для оператора преобразования идентификаторов. Это не здорово.
Ответ №1:
Вы можете сделать это с помощью оператора преобразования, который возвращает a myclass
с указанным типом const. Это выглядит так
template<typename T>
struct myclass
{
T foo;
operator myclass<const T>() { return myclass<const T>{foo}; }
};
а затем в
int main()
{
myclass<int> a{42};
f(a); // should compile
}
компилятор неявно вызовет его для вас.
Если у вас уже есть myclass<const int>
и вы передаете его f
, вам не нужно беспокоиться о какой-либо двусмысленности, поскольку конструктор копирования является точным совпадением, так что это то, что вызывается. Однако, если вы хотите отключить оператор преобразования, когда T
он уже const
есть, вы можете использовать
template<typename U = T, std::enable_if_t<!std::is_const_v<U>, bool> = true>
operator myclass<const U>() { return myclass<const U>{foo}; }
Комментарии:
1. @Yashas В этом случае произойдет «постоянный коллапс», вы все равно получите
const T
.myclass<const int>
этоoperator myclass<const T>
будет comeoperator myclass<const const int>
, который сворачивается вoperator myclass<const int>
2. Я немного смущен. Оператор преобразования для преобразования из
X
вX
не имеет особого смысла? Это должен быть оператор присваивания?3. Я подумал, что мне нужно будет условно включить оператор преобразования.
4. @Yashas «что, если T уже имеет значение const?» Он будет скомпилирован, если
foo
правильно инициализирован .5. @Yashas Если у вас уже есть
myclass<const T>
, то он не будет вызывать оператор преобразования, поскольку конструктор копирования является точным совпадением.