2012-03-27 4 views
1

Я хотел бы разбить компиляцию, если объект объявлен как const.Проверьте, объявлен ли объект const

Следующая не работает:

#include <type_traits> 

struct A { 

    A() : v(0) 
    { 
     static_assert(! std::is_const<decltype(*this)>::value, "declared as const"); 
    } 

    int& AccessValue() const 
    { 
     return const_cast< int& >(v); 
    } 

    int v; 
}; 

int main() 
{ 
    A a1; // ok, this compiles 
    const A a2; // no, this break the compilation 

    a1.AccessValue() = 5; // ok 
    a2.AccessValue() = 6; // OPS 
} 

Итак, есть ли способ разорвать компиляции, если объект этого типа объявлен сопзЬ?

+5

Я сомневаюсь, что это возможно. Чего вы хотите достичь? –

+1

Если кто-то получает 'const A', но не должен, компилятор будет в конечном итоге давать ошибки, в основном говорящие одно и то же (объявленные как const), поэтому вам действительно не нужно проверять такие вещи. – Shahbaz

+0

@AlexandreC. UB использовать const_cast для изменения из ссылки на const для ссылки без const, если объект не объявлен не const. Мне нужно использовать const_cast, но хотелось бы, чтобы люди не объявляли объекты этого типа const. –

ответ

3

Вы возглавляете неправильный путь.

Тип this является чисто диктуемым сигнатурой метода, в котором вы его используете. То есть всегда имеет тип cv T* const, где cv соответствует квалификаторам CV метода.

Следовательно, в конструкторе this всего лишь T* const.


const_cast является кодом запах, как правило, только использования при работе с const -broken устаревших библиотек ... или (иногда), чтобы не нарушать DRY.В новом коде вам не нужно использовать его.

Вы остались с выбором:

  • сделать AccessValue неконстантными, так как он не
  • объявить i как mutable.

Я бы посоветовал выбрать прежнее решение. Отказ от дескриптора атрибута private уже плох (разрывает инкапсуляцию), не нужно также нарушать корректность const.

+2

'this' никогда не' U const'. Это rvalue. 'const' не имеет смысла для не-объектов rvalues, поэтому нет неклассических/non-array rvalues ​​этого типа –

+0

@ JohannesSchaub-litb: это, я думаю, это легальный подход. На практике [это квалифицировано] (http://ideone.com/Gzgyg). Возможно, потому, что это помогает компилятору диагностировать плохо сформированные звонки? (избегая добавления посторонней логики для 'this') –

+0

нет, на практике gcc имеет ошибку. –

0

вы можете иметь несколько переменных, относящихся к одному и тому же объекту, некоторые mutable и некоторые const. Например:

A a1; 
const A &a2 = a1; 
A * const pa = &a1; 
f(a1); 
.... 
void f(const A &a); 

должны это быть разрешены в Вашем случае? Преобразование из mutable в const подразумевается наоборот. Может быть, если вы приведете пример, это поможет.

EDIT: (в ответ на модифицированный код) с объектом const вы можете вызвать только функцию const-члена. почему нет:

int& AccessValue() 
{ 
    return v; 
} 

компилятор с жалуйтесь, если вы звоните AccessValue на не объект Уст.

+0

Изменен мой пример. Надеюсь, что лучше сейчас –

1

Для вашего конкретного примера, что делает i изменяемый бы достичь своей цели:

int& AccessValue() const 
{ 
    return v; 
} 

mutable int v; 

Это из §7.1.6.1/4 [dcl.type.cv]:

за исключением того, любой член класса, объявленный mutable (7.1.1), может быть изменен, любая попытка изменить объект const во время его жизни (3.8) приводит к неопределенному поведению.

Обратите внимание, что вы не можете изменить v с помощью указателя на член на константный объект - §5.5/5 n3290 проекта [expr.mptr.oper]:

[Примечание: невозможно использовать указатель на элемент, который ссылается на изменяемый элемент, чтобы изменить объект класса const. Например,

struct S { 
S() : i(0) { } 
mutable int i; 
}; 

void f() 
{ 
const S cs; 
int S::* pm = &S::i; // pm refers to mutable member S::i 
cs.*pm = 88;   // ill-formed: cs is a const object 
} 

- конец примечание]

+0

Но у меня нет указателя на переменную-член. Поэтому применяется [7.1.6.1/5, последний C++ 11], там разрешено изменять его. Есть даже пример –

+0

Да, изменчивый член работает. Я просто указывал, что есть некоторые вещи, которые вы не можете сделать, даже если член изменен - ​​с использованием указателя на участника. Но пока вы этого не делаете, это хорошо. – Mat

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