Сообщение Re[4]: constexpr + mutable от 10.09.2023 11:34
Изменено 10.09.2023 11:43 Sm0ke
Re[4]: constexpr + mutable
Здравствуйте, YuriV, Вы писали:
S>>В рантайм Меняется состояние constexpr константы.
YV>constexpr говорит лишь о том, что компилятор сначала может попытаться вычислить значение выражение в компайл-тайм и если по каким-то причинам не может, то забывает о constexpr, неважно что это объявление метода или объекта. Выражение становиться просто константным, а мьютабл вы сами написали в классе. Так что ничего занятного.
constexpr у метода прдоставляет возможность вызвать этот метод не только в run-time, но и в compile-time.
Однако эту возможность constexpr не гарантирует.
Компилятор решает исходя из контекста вызова — является ли этот вызов compile-time вычислением, или run-time вычислением.
В случае compile-time происходит проверка допустимости выражения (и в вызове может быть отказано).
В коде моего исходного поста ...
... метод get() const меняет mutable свойство того объекта, который лежит за пределами body этого метода.
И компилятор запрещает вызов этого метода в compile-time, несмотря на то что метод constexpr.
пруф: https://godbolt.org/z/vqvrf95PM (другой пример)
Но даже если убрать инкремент, компилятор всё равно запретит (из-за чтения mutable у внешнего объекта).
пруф: https://godbolt.org/z/P3aq8n613 (ещё другой пример)
А что если обращаться в методе get() к mutable свойству у локального объекта?
проверим: https://godbolt.org/z/nq3TT4zbr (пример с локальным объектом метода get)
Компилируется!
S>>В рантайм Меняется состояние constexpr константы.
YV>constexpr говорит лишь о том, что компилятор сначала может попытаться вычислить значение выражение в компайл-тайм и если по каким-то причинам не может, то забывает о constexpr, неважно что это объявление метода или объекта. Выражение становиться просто константным, а мьютабл вы сами написали в классе. Так что ничего занятного.
constexpr у метода прдоставляет возможность вызвать этот метод не только в run-time, но и в compile-time.
Однако эту возможность constexpr не гарантирует.
Компилятор решает исходя из контекста вызова — является ли этот вызов compile-time вычислением, или run-time вычислением.
например | |
enum { n_value = some_funct() // compile-time call }; | |
В случае compile-time происходит проверка допустимости выражения (и в вызове может быть отказано).
В коде моего исходного поста ...
#include <iostream>
struct t_const_mut
{
// data
mutable int
value;
constexpr int
get() const
{ return ++this->value; }
};
constexpr const t_const_mut // и constexpr и const
g_obj{0}; // глобальная ячейка
int main()
{
std::cout
<< g_obj.get() << ' '
<< g_obj.get() << '\n';
return 0;
}
... метод get() const меняет mutable свойство того объекта, который лежит за пределами body этого метода.
И компилятор запрещает вызов этого метода в compile-time, несмотря на то что метод constexpr.
пруф: https://godbolt.org/z/vqvrf95PM (другой пример)
clang | |
<source>:18:5: error: non-type template argument is not a constant expression TAG<g_obj.get()> g_tag; ^~~~~~~~~~~ <source>:11:12: note: a constant expression cannot modify an object that is visible outside that expression { return ++this->value; } ^ <source>:18:11: note: in call to '&g_obj->get()' TAG<g_obj.get()> g_tag; ^ 1 error generated. Compiler returned: 1 | |
Но даже если убрать инкремент, компилятор всё равно запретит (из-за чтения mutable у внешнего объекта).
пруф: https://godbolt.org/z/P3aq8n613 (ещё другой пример)
clang | |
<source>:18:5: error: non-type template argument is not a constant expression TAG<g_obj.get()> g_tag; ^~~~~~~~~~~ <source>:11:12: note: read of mutable member 'value' is not allowed in a constant expression { return this->value; } ^ <source>:18:11: note: in call to '&g_obj->get()' TAG<g_obj.get()> g_tag; ^ <source>:7:3: note: declared here value; ^ 1 error generated. Compiler returned: 1 | |
А что если обращаться в методе get() к mutable свойству у локального объекта?
проверим: https://godbolt.org/z/nq3TT4zbr (пример с локальным объектом метода get)
ASM generation compiler returned: 0
Execution build compiler returned: 0
Program returned: 0
1 1
Компилируется!
#include <iostream>
struct t_const_mut
{
// data
mutable int
value;
constexpr int
get() const
{ t_const_mut v{}; return ++v.value; }
};
constexpr const t_const_mut
g_obj{0};
template <int I> struct TAG {};
TAG<g_obj.get()> g_tag;
int main()
{
std::cout
<< g_obj.get() << ' '
<< g_obj.get() << '\n';
return 0;
}
Re[4]: constexpr + mutable
Здравствуйте, YuriV, Вы писали:
S>>В рантайм Меняется состояние constexpr константы.
YV>constexpr говорит лишь о том, что компилятор сначала может попытаться вычислить значение выражение в компайл-тайм и если по каким-то причинам не может, то забывает о constexpr, неважно что это объявление метода или объекта. Выражение становиться просто константным, а мьютабл вы сами написали в классе. Так что ничего занятного.
constexpr у метода прдоставляет возможность вызвать этот метод не только в run-time, но и в compile-time.
Однако эту возможность constexpr не гарантирует.
Компилятор решает исходя из контекста вызова — является ли этот вызов compile-time вычислением, или run-time вычислением.
В случае compile-time происходит проверка допустимости выражения (и в вызове может быть отказано).
В коде моего исходного поста ...
... метод get() const меняет mutable свойство того объекта, который лежит за пределами body этого метода.
И компилятор запрещает вызов этого метода в compile-time, несмотря на то что метод является constexpr.
пруф: https://godbolt.org/z/vqvrf95PM (другой пример)
Но даже если убрать инкремент, компилятор всё равно запретит (из-за чтения mutable у внешнего объекта).
пруф: https://godbolt.org/z/P3aq8n613 (ещё другой пример)
А что если обращаться в методе get() к mutable свойству у локального объекта?
проверим: https://godbolt.org/z/nq3TT4zbr (пример с локальным объектом метода get)
Компилируется!
S>>В рантайм Меняется состояние constexpr константы.
YV>constexpr говорит лишь о том, что компилятор сначала может попытаться вычислить значение выражение в компайл-тайм и если по каким-то причинам не может, то забывает о constexpr, неважно что это объявление метода или объекта. Выражение становиться просто константным, а мьютабл вы сами написали в классе. Так что ничего занятного.
constexpr у метода прдоставляет возможность вызвать этот метод не только в run-time, но и в compile-time.
Однако эту возможность constexpr не гарантирует.
Компилятор решает исходя из контекста вызова — является ли этот вызов compile-time вычислением, или run-time вычислением.
например | |
enum { n_value = some_funct() // compile-time call }; | |
В случае compile-time происходит проверка допустимости выражения (и в вызове может быть отказано).
В коде моего исходного поста ...
#include <iostream>
struct t_const_mut
{
// data
mutable int
value;
constexpr int
get() const
{ return ++this->value; }
};
constexpr const t_const_mut // и constexpr и const
g_obj{0}; // глобальная ячейка
int main()
{
std::cout
<< g_obj.get() << ' '
<< g_obj.get() << '\n';
return 0;
}
... метод get() const меняет mutable свойство того объекта, который лежит за пределами body этого метода.
И компилятор запрещает вызов этого метода в compile-time, несмотря на то что метод является constexpr.
пруф: https://godbolt.org/z/vqvrf95PM (другой пример)
clang | |
<source>:18:5: error: non-type template argument is not a constant expression TAG<g_obj.get()> g_tag; ^~~~~~~~~~~ <source>:11:12: note: a constant expression cannot modify an object that is visible outside that expression { return ++this->value; } ^ <source>:18:11: note: in call to '&g_obj->get()' TAG<g_obj.get()> g_tag; ^ 1 error generated. Compiler returned: 1 | |
Но даже если убрать инкремент, компилятор всё равно запретит (из-за чтения mutable у внешнего объекта).
пруф: https://godbolt.org/z/P3aq8n613 (ещё другой пример)
clang | |
<source>:18:5: error: non-type template argument is not a constant expression TAG<g_obj.get()> g_tag; ^~~~~~~~~~~ <source>:11:12: note: read of mutable member 'value' is not allowed in a constant expression { return this->value; } ^ <source>:18:11: note: in call to '&g_obj->get()' TAG<g_obj.get()> g_tag; ^ <source>:7:3: note: declared here value; ^ 1 error generated. Compiler returned: 1 | |
А что если обращаться в методе get() к mutable свойству у локального объекта?
проверим: https://godbolt.org/z/nq3TT4zbr (пример с локальным объектом метода get)
ASM generation compiler returned: 0
Execution build compiler returned: 0
Program returned: 0
1 1
Компилируется!
#include <iostream>
struct t_const_mut
{
// data
mutable int
value;
constexpr int
get() const
{ t_const_mut v{}; return ++v.value; }
};
constexpr const t_const_mut
g_obj{0};
template <int I> struct TAG {};
TAG<g_obj.get()> g_tag;
int main()
{
std::cout
<< g_obj.get() << ' '
<< g_obj.get() << '\n';
return 0;
}