Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

«constexpr» функции не имеют спецификатор «const»

Anna | 25.06.2014 | нет комментариев

Легко хотел Вас предупредить: С 14 не будет обратно совместим с C 11 в одном аспекте constexpr функций.

В С 11, если Вы определите constexpr функцию-член, то она неявно получит спецификатор const:

// C  11
struct NonNegative
{
  int i;
  constexpr int const& get() /*const*/ { return i; }
  int& get() { return i; }
};

Первое объявление функции get получит спецификатор const, даже если мы не укажем это очевидно. Следственно, эти две функции являются перегруженными: const и не-const версии.

В С 14 это будет теснее не так: оба объявления будут определять одиннаковую, не-const версию функции-члена с различающимися возвращаемыми значениями — это приведет к ошибке компиляции. Если Вы теснее начали применять constexpr функции и верите на неявный спецификатор const, то я советую Вам начать добавлять его очевидно, Дабы Ваш код продолжал компилироваться, если Вы решите перейти на компиляторы С 14.

Что не так с неявным const?

Задачи начнутся, если Вы попытаетесь применять наш тип дальнейшим образом:

// C  11
constexpr int i = NonNegative{2}.get(); // ERROR

Согласно (несколько странным) правилам С , при выборе функции-члена для временного объекта, не-constверсия предпочтительней const версии. Наша не-const функция-член get не является constexpr, следственно она не может быть использована для инициализации constexpr переменной и мы получим ошибку на этапе компиляции. Мы не можем сделать эту функцию constexpr, потому что это механически добавит спецификатор const

Я сказал, что правила подбора лучшей функции — странны, потому что они немножко противоречат тому, как мы выбираем лучшую функцию-нечлен для временных объектов. В этом случае мы выбираем const lvalue ссылки к не-const версии:

// C  11
constexpr int const& get(NonNegative const& n) { return n.i; }
constexpr int& get(NonNegative& n) { return n.i; }

NonNegative N = readValue();
constexpr int * P = &get(N);

int main() 
{ 
  *P = 1;
}

Глядите, что получается: глобальная переменная N не является константой. Следственно вторая, не-constперегруженная функция выбирается для вызова при инициализации указателя P. Но не-const функция при этом все равно имеет спецификатор constexpr! А все потому, что правило “constexpr обозначает const” используется только для неявного this довода нестатической функции-члена. constexpr функция может получить ссылку на не-const объект и воротить ссылку на не-const подобъект. Тут нет никаких задач: адрес глобального объекта непрерывен и знаменит во время компиляции. Впрочем значение по адресу P не непрерывно и может быть изменено позднее.

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

// C  11
constexpr NonNegative* address(NonNegative& n) { return &n; } 

NonNegative n{0}; // non-const
constexpr NonNegative* p = address(n);

Тут все работает отменно, но если Вы попытаетесь сделать address функцией членом, она перестанет трудиться:

// C  11
struct NonNegative
{
  // ...
  constexpr NonNegative* maddress() { return this; } // ERROR
};

NonNegative n{0}; // non-const
constexpr NonNegative* p = n.maddress();

Это потому, что maddress неявно определен со спецификатором constthis имеет тип NonNegative const* и не может быть конвертировано к NonNegative*.

Следует подметить, что это не сама функция-член является const, а неявный (this) довод функции. Объявление функции-члена может быть переписано в псевдо-коде как:

// PSEUDO CODE
struct NonNegative
{
  // ...
  constexpr NonNegative* maddress(NonNegative const& (*this)); 
};

И данный неявный довод функции, в различие от других доводов функций, получает (изредка неугодный) спецификатор const.

Эта асимметричность будет удалена в С 14. Если Вы хотите спецификатор const для неявного довода (this), Вам следует добавить его самим. Дальнейший код будет действительным в C 14:

// C  14
struct NonNegative
{
  int i;
  constexpr int const& get() const { return i; }
  constexpr int& get() { return i; }
};

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB