Автоматический вывод типа с const_cast не работает - PullRequest
0 голосов
/ 13 декабря 2018

В моей работе использование const_cast при некоторых обстоятельствах неизбежно.

Теперь мне нужно const_cast несколько довольно сложных типов, и на самом деле я не хочу записывать все эти типы беспорядка в выражениях const_cast<Clutter>, особенно если Clutter очень длинный.

Моей первой идеей было написать const_cast<>(myType), но мой компилятор не может вывести неконстантный тип myType.Поэтому я подумал о помощи своему компилятору и разработал следующий подход, который компилируется.

#include <stdlib.h>
#include <iostream>

int main(int, char**) {
    const int constVar = 6;
    using T = typename std::remove_cv<decltype(constVar)>::type;
    auto& var = const_cast<T&>(constVar);
    var *= 2;
    std::cout << &constVar << " " << &var << "\n"; // Same address!
    std::cout << constVar << " " << var << "\n";
    return EXIT_SUCCESS;
}

К сожалению, программа выдаёт мне вывод 6 12 вместо ожидаемого 6 6, который я действительно не понял?

Что не так с моим подходом?

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Если у вас есть

void foo(const int& a)
{
    const_cast<int&>(a) = 4;
}

, то

int a = 1;
foo(a);

совершенно законно, но

const int a = 1;
foo(a);

вызывает неопределенное поведение, потому что в foo,a изначально был const.

В некоторых случаях это полезно (обычно при взаимодействии со старой библиотекой C), но в большинстве случаев вы делаете что-то не так и должны переосмыслить свое решение.

И чтобы ответить, почему const_cast<> не вещь, я бы сказал, по двум причинам.Во-первых, когда вы делаете const_cast, вы должны действительно знать, что делаете, если какой-то шаблонный вывод был разрешен, это повысило бы вероятность возникновения непреднамеренных ошибок.И, во-вторых, const_cast также можно использовать для удаления volatile, и как компилятор может узнать, что вы хотите отбросить?

0 голосов
/ 13 декабря 2018

Из документации const_cast:

const_cast позволяет сформировать ссылку или указатель на неконстантный тип, который фактически ссылается на constобъект или ссылка или указатель на энергонезависимый тип, который фактически ссылается на энергозависимый объект.Изменение const-объекта через неконстантный путь доступа и обращение к энергозависимому объекту через энергонезависимое glvalue приводит к неопределенному поведению.

Итак, у вас есть неопределенное поведение.

Также представляет интерес эта заметка из определителей типа cv .

const object - объект, тип которого является const-квалифицированным, или не изменяемыйподобъект объекта const.Такой объект нельзя изменить: попытка сделать это напрямую является ошибкой во время компиляции, а попытка сделать это косвенно (например, путем изменения объекта const посредством ссылки или указателя на неконстантный тип) приводит к неопределенному поведению.

...