Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
748 / 351 / 72
Регистрация: 10.06.2014
Сообщений: 2,368
1

Ключевое слово constexpr: как определить удалось ли вычислить возвращаемое значение на этапе компиляции?

09.01.2017, 16:01. Просмотров 2078. Ответов 13
Метки нет (Все метки)

https://habrahabr.ru/post/228181/
Ключевое слово constexpr, добавленное в C++11, перед функцией означает, что если значения параметров возможно посчитать на этапе компиляции, то возвращаемое значение также должно посчитаться на этапе компиляции. Если значение хотя бы одного параметра будет неизвестно на этапе компиляции, то функция будет запущена в runtime (а не будет выведена ошибка компиляции).
Как определить удалось ли вычислить возвращаемое значение на этапе компиляции?
Я понимаю что можно анализировать код и делать вывод "вот этот кусок может быть вычислен на этапе компиляции"
А есть ли способ при компиляции узнать чего случилось на этапе компиляции а что ушло в рантайм (не проверяя самому на глаз и не делая догадки)?
И без чтения машинного кода)) Нужен простой способ определить это
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.01.2017, 16:01
Ответы с готовыми решениями:

Как на этапе компиляции определить принадлежность к классу?
Есть шаблонный класс, который в зависимости от переданного класса в параметре подбирает нужный...

Как добавить анонимный тип в объект не на этапе компиляции, а на этапе выполнения программы? Надо для routes.MapRoute
В приложении ASP.NET MVC у меня есть xml файл с маршрутами типа: <route url="Home/{par1}/{par2}"...

Не удалось изменить возвращаемое значение для List<T>.this[int]
listStructSelected.byteStatus = getStatus(); Ошибка: Ошибка 25 Не удалось изменить возвращаемое...

Определить, в введенном предложении слово, которое состоит из тех же букв, что и заданное ключевое слово.
Ввести предложения и ключевое слово. Определить, в введенном предложении слово, которое состоит из...

13
Форумчанин
Эксперт CЭксперт С++
8161 / 5009 / 1436
Регистрация: 29.11.2010
Сообщений: 13,455
09.01.2017, 16:06 2
Лучший ответ Сообщение было отмечено Undisputed как решение

Решение

Присвоить результат выполнения constexpr переменной. Если выдаст ошибку компиляции - нельзя.
1
748 / 351 / 72
Регистрация: 10.06.2014
Сообщений: 2,368
09.01.2017, 16:29  [ТС] 3
Цитата Сообщение от MrGluck Посмотреть сообщение
Присвоить результат выполнения constexpr переменной. Если выдаст ошибку компиляции - нельзя.
Понял спасибо!

Добавлено через 51 секунду
А есть способ что бы не мучиться и не проверять каждый раз вручную? Это надоест если кода много
0
Форумчанин
Эксперт CЭксперт С++
8161 / 5009 / 1436
Регистрация: 29.11.2010
Сообщений: 13,455
09.01.2017, 16:34 4
Цитата Сообщение от sys_beginner Посмотреть сообщение
А есть способ что бы не мучиться и не проверять каждый раз вручную? Это надоест если кода много
Изначально при написании функции можно прикинуть варианты её использования и понять, есть ли вариант её работы на этапе компиляции. Да и с не constexpr объектами она не разрешит работать.
1
748 / 351 / 72
Регистрация: 10.06.2014
Сообщений: 2,368
09.01.2017, 16:37  [ТС] 5
Цитата Сообщение от MrGluck Посмотреть сообщение
Изначально при написании функции можно прикинуть варианты её использования и понять, есть ли вариант её работы на этапе компиляции.
Этого и хотелось избежать)) Ок, понял
Спасибо ещё раз

Добавлено через 47 секунд
Цитата Сообщение от MrGluck Посмотреть сообщение
Да и с не constexpr объектами она не разрешит работать.
Хоть какое то утешение
0
Don't worry, be happy
16958 / 9839 / 1895
Регистрация: 27.09.2012
Сообщений: 24,392
Записей в блоге: 2
14.01.2017, 17:56 6
Цитата Сообщение от sys_beginner Посмотреть сообщение
Как определить удалось ли вычислить возвращаемое значение на этапе компиляции?
Немного тут покумекал, получилась такая фиговина:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
 
 
#define CAN_BE_COMPILE_TIME_EVALUATE(FUNC, ...) \
[&]() {\
    auto foo________ = [&]() noexcept(false) {\
        return FUNC(__VA_ARGS__);\
    };\
    return noexcept(foo________()); \
}()
 
 
 
constexpr int foo(int x)
{
   int sum = 0;
   for (int i = 0; i < 10; ++i) {
      sum += i;
   }
   return sum;
}
 
 
 
int main()
{
    const int x1 = 20;
    int x2 = 10;
    constexpr bool b1 = CAN_BE_COMPILE_TIME_EVALUATE(foo, x1);
    constexpr bool b2 = CAN_BE_COMPILE_TIME_EVALUATE(foo, x2);
    std::cout << b1 << std::endl;
    std::cout << b2 << std::endl;
    constexpr int f = foo(x1);
    //constexpr int f = foo(x2);//error
}
в отличии от способа с инициализацией constexpr,
не вызывает ошибку компиляции,
хотя и вычисляется на этапе компиляции.
Может и не везде будет работать, не знаю.

P.S. Тревога! В коде TAB'ы.
P.P.S. А еще в коде вариативные макросы gcc и возможности C++17
7
Эксперт CЭксперт С++
5047 / 2230 / 330
Регистрация: 20.02.2013
Сообщений: 5,600
Записей в блоге: 24
14.01.2017, 18:10 7
 Комментарий модератора 
sys_beginner, пожалуйста, прочитайте правила форума.
Особое внимание обратите на пункт 4.3 (порядок именования тем).

.
1
748 / 351 / 72
Регистрация: 10.06.2014
Сообщений: 2,368
14.01.2017, 20:04  [ТС] 8
Croessmah,
Спасибо, только не пойму что происходит в коде.
У вас создается анонимная функция с захватом ссылки без имени, как это работает? Как обратиться к такому параметру без имени и зачем он там нужен?

Внутри функции у вас создается ещё одна функция, которая принимает тестируюмую функцию как аргумент и передает туда вариативные параметры. Но потом возвращается return noexcept(foo________()); - не понял что именно тут происходит, noexcept вроде пишется в описании функции а не при возврате значения
0
Любитель чаепитий
3526 / 1638 / 506
Регистрация: 24.08.2014
Сообщений: 5,575
Записей в блоге: 1
14.01.2017, 21:34 9
Цитата Сообщение от sys_beginner Посмотреть сообщение
как это работает?
Захватывает все переменные по ссылке в данном скоупе.
1
748 / 351 / 72
Регистрация: 10.06.2014
Сообщений: 2,368
14.01.2017, 22:19  [ТС] 10
Цитата Сообщение от GbaLog- Посмотреть сообщение
Захватывает все переменные по ссылке в данном скоупе.
Спасибо, действительно захватывает. Но похоже все таки не по ссылке

C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <map>
#include <functional>
 
int main() {
    int n = 1000;
    std::function<void(void)> f = [&]()
    {
        n = 2000;
    };
    std::cout << n;//1000
}
http://rextester.com/GLZ22737
0
Don't worry, be happy
16958 / 9839 / 1895
Регистрация: 27.09.2012
Сообщений: 24,392
Записей в блоге: 2
14.01.2017, 22:22 11
Цитата Сообщение от sys_beginner Посмотреть сообщение
не по ссылке
а вызывать кто будет?
C++
1
f();
1
748 / 351 / 72
Регистрация: 10.06.2014
Сообщений: 2,368
14.01.2017, 22:29  [ТС] 12
GbaLog-,
Я очень сильно тупанул ))

Croessmah,
Точно, спасибо!

Добавлено через 1 минуту
Ещё и map почему то добавил в хедера)))
Пойду отдохну что ли
0
26 / 29 / 8
Регистрация: 02.04.2016
Сообщений: 286
15.01.2017, 15:56 13
Почему-то проблемы подобная проверка не вызывала. Если я делал функцию constexpr, то делал и static_assert для проверки возвращаемого значения. По-моему, это гораздо проще, чем создание переменных или макросов.
0
Don't worry, be happy
16958 / 9839 / 1895
Регистрация: 27.09.2012
Сообщений: 24,392
Записей в блоге: 2
15.01.2017, 17:32 14
Цитата Сообщение от Lyosha12 Посмотреть сообщение
По-моему, это гораздо проще, чем создание переменных или макросов.
Разница в том, что можно вычислить в compile-time,
может ли значение функции быть вычислено в commile-time.
Для static_assert или инициализацию constexpr упремся в ошибку,
а так может и можно что-то намудрить будет (понятия не имею что).
Т.к. конечное значение constexpr, то можно его задействовать как-то,
например, в constexpr if:

C++
1
2
3
4
5
if constexpr (b1) {
   //...
} else {
   //...
}
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.01.2017, 17:32

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Как определить возвращаемое значение для пользовательского элемента управления?
Создаю пользовательский элемент управления. На поле UserControl1 перетаскиваю элемент TextBox, для...

Структура в List<>, "Не удалось изменить возвращаемое значение"
Всем привет. namespace { struct STRUCT { internal float a; ...

Не удалось изменить возвращаемое значение "Transform.position", т.к. оно не является переменной
Не удалось изменить возвращаемое значение &quot;Transform.position&quot;, т.к. оно не является переменной....

Как на этапе компиляции создать необходимое количество шаблонных функций?
Есть алгоритм, который использует функцию от одного аргумента. Этот же алгоритм должен использовать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.