Проверьте, объявлен ли объект const - PullRequest
1 голос
/ 27 марта 2012

Я хотел бы прервать компиляцию, если объект объявлен как 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
}

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

Ответы [ 3 ]

3 голосов
/ 27 марта 2012

Вы идете по неверному пути.

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

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


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

У вас есть выбор:

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

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

1 голос
/ 27 марта 2012

Для вашего конкретного примера, сделав 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, используя указатель на член для объекта const - §5.5 / 5 из n3290 draft [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 голосов
/ 27 марта 2012

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

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

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

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

int& AccessValue()
{
    return v;
}

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

...