const_cast в шаблоне.Существует ли модификатор unconst?
-
19-09-2019 - |
Вопрос
У меня есть шаблонный класс, подобный этому:
template<T>
class MyClass
{
T* data;
}
Иногда я хочу использовать класс с постоянным типом T следующим образом:
MyClass<const MyObject> mci;
но я хочу изменить данные, используя const_cast<MyObject*>data
(не важно , почему , но MyClass
это класс интеллектуального указателя с подсчетом ссылок, который сохраняет количество ссылок в самих данных. MyObject
является производным от некоторого типа, который содержит значение count.Данные не должны быть изменены, но счетчик должен быть изменен интеллектуальным указателем.).
Есть ли способ удалить константность из T
?Вымышленный код:
const_cast<unconst T>(data)
?
Решение
Самым простым способом здесь было бы сделать счетчик ссылок изменяемым.
Однако, если вас интересует, как это будет работать с const_cast
, затем переопределение boost's remove_const
должно быть довольно простым:
template <class T>
struct RemoveConst
{
typedef T type;
};
template <class T>
struct RemoveConst<const T>
{
typedef T type;
};
const_cast<typename RemoveConst<T>::type*>(t)->inc();
Другие советы
У вас есть ответ.const_cast работает в обоих направлениях:
char* a;
const char* b;
a = const_cast<char*>(b);
b = const_cast<const char*>(a); // not strictly necessarily, just here for illustration
Что касается вашей конкретной проблемы, рассматривали ли вы ключевое слово mutable?Это позволяет изменять переменную-член внутри метода const.
class foo {
mutable int x;
public:
inc_when_const() const { ++x; }
dec_when_const() const { --x; }
};
Сделайте счетчик ссылок изменяемым в классе, управляемом вашим навязчивым указателем.Это вполне разумно и точно отражает "логическую постоянство", т. е.изменение количества ссылок на объект не отражает никаких изменений в состоянии самого объекта.Другими словами, счетчик ссылок логически не является частью объекта - объект просто является удобным местом для хранения этих полусвязанных данных.
Если вы можете использовать Boost, библиотека признаков типа предоставляет удаление_const метафункция, которая это делает.
Вот мой C ++ 11 unconst
функция template
.
Если вы используете его, вы флиртуете с неопределенное поведение.Вы были предупрежден.
// on Ubuntu (and probably others) compile and test with
// g++ -std=c++11 test.c && ./a.out ; echo $?
template < class T > T & unconst ( T const & t ) {
return const_cast < T & > ( t ) ;
}
// demonstration of use
struct {
const int n = 4;
} s;
int main () {
unconst ( s.n ) = 5;
return s.n;
}