Пока не придумал как это можно использовать. Просто занятный факт.
p/s gblt
При попытке вызвать t_const_mut::get() в consteval контексте компилятор от vs выдаёт Internal compiler error.
В то время как clang и gcc этого делать не позволяет, ссылаясь на чтение mutable мембера в compile-time. (или на изменение внешнего объекта, видимого за пределами метода)
Здравствуйте, Sm0ke, Вы писали:
S>constexpr + mutable (можно менять значение compile time константы)
S>Пока не придумал как это можно использовать. Просто занятный факт.
Что тут занятного ? Констэкспр перестал вычисляться в компайлтайм и стал вычисляться в рантайм. Так и было задумано. Мьютабл и констэкспр никак не связанные вещи.
S>p/s gblt S>При попытке вызвать t_const_mut::get() в consteval контексте компилятор от vs выдаёт Internal compiler error. S>В то время как clang и gcc этого делать не позволяет, ссылаясь на чтение mutable мембера в compile-time. (или на изменение внешнего объекта, видимого за пределами метода)
И это было задумано. Констевал требует возможности вычисления в компайл-тайм.
Здравствуйте, YuriV, Вы писали:
YV>Что тут занятного ? Констэкспр перестал вычисляться в компайлтайм и стал вычисляться в рантайм. Так и было задумано. Мьютабл и констэкспр никак не связанные вещи.
Здравствуйте, reversecode, Вы писали:
R>constexpr который свершился или который не получился и компилер дальше пошел по обычным правилам ?
Нет. Свершился или не получился — это про другое, это когда функция объявляется constexpr и вот непосредственно ее код то ли можно исполнить во время компиляции то ли нет. В текущем топике речь идет не об этом, но о constexpr переменных/объектах.
Здравствуйте, Sm0ke, Вы писали:
S>Здравствуйте, YuriV, Вы писали:
YV>>Что тут занятного ? Констэкспр перестал вычисляться в компайлтайм и стал вычисляться в рантайм. Так и было задумано. Мьютабл и констэкспр никак не связанные вещи.
S>В рантайм Меняется состояние constexpr константы.
constexpr говорит лишь о том, что компилятор сначала может попытаться вычислить значение выражение в компайл-тайм и если по каким-то причинам не может, то забывает о constexpr, неважно что это объявление метода или объекта. Выражение становиться просто константным, а мьютабл вы сами написали в классе. Так что ничего занятного.
Здравствуйте, YuriV, Вы писали:
YV>Здравствуйте, Sm0ke, Вы писали:
S>>Здравствуйте, YuriV, Вы писали:
YV>>>Что тут занятного ? Констэкспр перестал вычисляться в компайлтайм и стал вычисляться в рантайм. Так и было задумано. Мьютабл и констэкспр никак не связанные вещи.
S>>В рантайм Меняется состояние constexpr константы. YV>constexpr говорит лишь о том, что компилятор сначала может попытаться вычислить значение выражение в компайл-тайм и если по каким-то причинам не может, то забывает о constexpr, неважно что это объявление метода или объекта. Выражение становиться просто константным, а мьютабл вы сами написали в классе. Так что ничего занятного.
Здравствуйте, YuriV, Вы писали: S>>В рантайм Меняется состояние constexpr константы. YV>constexpr говорит лишь о том, что компилятор сначала может попытаться вычислить значение выражение в компайл-тайм и если по каким-то причинам не может, то забывает о constexpr, неважно что это объявление метода или объекта. Выражение становиться просто константным, а мьютабл вы сами написали в классе. Так что ничего занятного.
constexpr у метода прдоставляет возможность вызвать этот метод не только в run-time, но и в compile-time. Однако эту возможность constexpr не гарантирует.
Компилятор решает исходя из контекста вызова — является ли этот вызов compile-time вычислением, или run-time вычислением.
... метод 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
#include <iostream>
struct t_const_mut
{
// datamutable int
value;
constexpr int
get() const
{ return this->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;
}
А что если обращаться в методе get() к mutable свойству у локального объекта?
проверим: https://godbolt.org/z/nq3TT4zbr (пример с локальным объектом метода get)
Здравствуйте, sergii.p, Вы писали:
SP>Здравствуйте, Sm0ke, Вы писали:
S>>constexpr + mutable (можно менять значение compile time константы)
SP>вот такое должно работать на gcc/msvc
SP>
SP>constexpr auto l = []() mutable { return __COUNTER__; };
SP>
SP>значение compile time константы не меняем, но constexpr + mutable
используемый тут спецификатор mutable не относится к состоянию объекта l
Здравствуйте, sergii.p, Вы писали:
SP>Здравствуйте, vopl, Вы писали:
V>>используемый тут спецификатор mutable не относится к состоянию объекта l
SP>спасибо, кэп.
На здоровье, конечно. Если для тебя это очевидно — зачем тогда говоришь что тут constexpr+mutable?