идиоматический способ преобразования оператора `class <T>` в `class <const T>` - PullRequest
1 голос
/ 12 апреля 2019

Предположим, существует класс шаблона 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 Ответ

5 голосов
/ 12 апреля 2019

Вы можете сделать это с помощью оператора преобразования, который возвращает 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}; }
...