2009-10-04 2 views
5

У меня есть класс шаблона, как это:const_cast в шаблоне. Есть ли модификатор unconst?

template<T> 
class MyClass 
{ 
    T* data; 
} 

Иногда, я хочу использовать класс с постоянным типа Т следующим образом:

MyClass<const MyObject> mci; 

, но я хочу изменить данные с помощью const_cast<MyObject*>data (неважно почему, но MyClass - класс интеллектуальных указателей ссылок, который хранит счетчик ссылок в самих данных. MyObject получен из некоторого типа, который содержит счет. Данные не должны быть изменены, но счет должен быть изменен умный указатель.).

Есть ли способ удалить константу от T? Выведенный код:

const_cast<unconst T>(data) 

?

ответ

11

Простейший способ здесь - сделать счетчик ссылок изменчивым.

Однако, если вы заинтересованы в том, как он будет работать с const_cast, то реализовав подталкивание-х 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(); 
+0

Благодарим вас за объяснение того, как remove_const работает со мной. – danatel

+3

@ danatel: Вы действительно не хотите использовать remove_const.Изменение значения константы путем отбрасывания константы - неопределенное поведение. Вы хотите использовать __mutable__ в переменной refcount. –

+0

:-) Я использую mutable. Мне не нужно решение моей проблемы, проблема была там как иллюстрация (пожалуйста, прочитайте оригинал сообщения) - Мне было любопытно, есть ли способ удалить постоянство. – danatel

5

У вас есть ответ. 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 

Что касается конкретной проблемы, считаете ли вы изменяемое ключевое слово? Он позволяет изменять переменную-член внутри метода const.

class foo { 
    mutable int x; 
public: 
    inc_when_const() const { ++x; } 
    dec_when_const() const { --x; } 
}; 
+0

Но это класс шаблонов. Т - это нечто. Возникает вопрос: как мне создать что-то из T? – danatel

+1

+1 Mutable - ответ здесь. – UncleBens

3

Если вы можете использовать Boost, библиотека типа Черты характера обеспечивает remove_const metafunction, что делает это.

+0

К сожалению, в этом проекте я не могу использовать Boost. Но если бы был простой способ сделать это в стандартном C++, тогда никто не напишет remove_const. Поэтому такого пути нет. – danatel

+0

Вы прочитали другие ответы? Boost - это просто мета-шаблонная версия, просто используйте const_cast и удалите const из нее или измените, например, jumcchellio. – GManNickG

4

Сделать счетчик ссылок измененным в классе, управляемом вашим интрузивным указателем. Это вполне разумно и точно отражает «логическую консистенцию» - т. Е. Изменение счетчика ссылок объекта не отражает никакого изменения состояния самого объекта. Другими словами, счетчик ссылок не является логически частью объекта - объект просто оказывается удобным местом для хранения этих полу-несвязанных данных.

0

Вот мой 11 unconst C++ функция template.

Если вы используете его, вы заигрываете с undefined behavior. Вы были предупреждены .

// 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; 
} 
+0

Я думаю, что это будет проще и будет иметь такой же эффект: 'template T & unconst (T const & t) {return const_cast (t);}'. – alfC

+0

Спасибо! Это проще и, похоже, работает. Я задавался вопросом, какая разница между «typename» и «class». – mpb

Смежные вопросы