Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 08.08.2014
Сообщений: 21
1

Рекурсивный вызов constexpr функции

17.11.2019, 13:52. Показов 1080. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Приветствую уважаемые форумчане. Возможно ли реализовать указанное в теме телодвижение, с условием передачи в качестве входного параметра в каждой итерации нового объекта. Насколько я понимаю, есть ограничение по возможным типам, да? Интегральные типы вроде проходят. Пример который пытаюсь завести:
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
36
37
38
39
struct Test {
    const int test = 0; 
    constexpr Test(int _test) :test(_test) {}
    constexpr Test() : test(1) {}
};
 
//любой из вариантов бы завести:
template <const Test & argtest> constexpr Test funcTest() {
    if (argtest.test < 4) return Test{ argtest.test + 1 };// - это работает                                                        
    //return funcTest < Test{argtest.test + 1}> ();//это нет
    
    //static 
    //constexpr auto temp = Test{ argtest.test + 1 };
    //return funcTest <temp> (); //и это нет - что со static, что без static
    return  Test(argtest.test + 1);
};
 
template <const Test * argtest> constexpr Test* funcTestP() {
    if (argtest->test < 4) return &Test{ argtest->test + 1 };// - это работает
        //return funcTestP < &Test{ argtest->test + 1 } > ();//это нет
    return  &Test(argtest->test + 1);
};
 
constexpr Test t;
constexpr Test T = funcTest<t>();
constexpr Test* Tt = funcTestP<&t>();
 
//работающая классика:
struct Ta {
    const int heap = 0;
    const Ta* tail = nullptr;
};
template <const int N> constexpr Ta genList() {
    if constexpr (N > 3) return Ta{ N,&(genList<N - 2>()) };
    else return Ta{ N,&(genList<N - 1>()) };
    //return (N > 3) ? Ta{ N,&(D3<N - 2>()) } : Ta{ N,&(D3<N - 1>()) };//размечтался
}
template <> constexpr Ta genList<0>() { return Ta{ 0,nullptr }; }
constexpr Ta t_= genList<5>();
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.11.2019, 13:52
Ответы с готовыми решениями:

Рекурсивный вызов функции main
Не понимаю, где здесь рекурсивный вызов main() будет? Написал такой код: #include&lt;iostream&gt;...

Косвенный рекурсивный вызов функции
Добрый вечер. Пишу программу, вычисляющую массивы. Внутри программы есть две(пока что одна)...

рекурсивный вызов функции-члена
как осуществить рекурсивный вызов функции члена?

Используя рекурсивный вызов функции вычислить сумму заданного числа элементов ряда
В программировании я просто дуб дубом, но нужно срочно сделать одну задачу в Qt. Сама задача: ...

10
18833 / 9835 / 2404
Регистрация: 30.01.2014
Сообщений: 17,273
17.11.2019, 14:09 2
Martmath, честно говоря, там где у вас написано "работает", тоже не работает, потому что берете адрес временного объекта. Например так:
C++
1
return &Test{ argtest->test + 1 };// - это работает
делать нельзя.

Лучше опишите внятно словами что вы хотите сделать.
1
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
17.11.2019, 14:20 3
Цитата Сообщение от Martmath Посмотреть сообщение
argtest->test < 4)
Martmath, не видно оператора сравнения который это сможет. Вообще, вопрос ни как не понятен. Глядя во тьму могу произнести следующее:
Рекурсия времени компиляции возможна и лежит в основе многих современных приёмов и типов. Но она требует быть вычислимой на стадии компиляции.
0
0 / 0 / 0
Регистрация: 08.08.2014
Сообщений: 21
17.11.2019, 15:27  [ТС] 4
Благодарю за внимание:
там где у вас написано "работает", тоже не работает, потому что берете адрес временного объекта. ..
Компилятор от микрософт (с выбором с++17 стандарта), если не итерировать - обрабатывает этот код без ошибок.
Лучше опишите внятно словами что вы хотите сделать.
:
Возможно ли в ТЕЛЕ constexpr функции создать(или изменить существующий constexpr) объект времени компиляции. После, в этом же теле, запихнуть рекурсивно в нее же (ну или, хотя бы, в другую constexpr функцию) данный обьект в качестве входного параметра.

Все примеры из инета, в основном, крутятся вокруг интергальных типов а-ля int: собственно пример ниже из моего кода (с рекурсивным листом) вполне себе отрабатывает. С обьектами - глуховато ((.
Вот тут template_parameters пишут про "...a pointer type (to object or to function);... " вот собственно "a pointer type to object" и интересен.

Добавлено через 8 минут
...если бы получилось без макросов (я про BOOST_PP_SEQ_FOR_EACH_I и BOOST_PP_SEQ_ENUM) было бы здорово...

Добавлено через 24 минуты
Извиняюсь за "мутную" формулировку - насколько я понял, для подобного рода задачи, в возвращаемом в конечной итерации значении должны быть "места" для всех "темповых" переменных используемых в предыдущих итерациях?
0
18833 / 9835 / 2404
Регистрация: 30.01.2014
Сообщений: 17,273
17.11.2019, 16:59 5
Цитата Сообщение от Martmath Посмотреть сообщение
обрабатывает этот код без ошибок.
Компилируемость кода каким-то конкретным компилятором еще не означает его работоспособность. Это можно вышить золотыми буквами и где-нибудь повесить, чтобы никогда об этом не забывать.

Кроме того, есть и другие компиляторы, которые закономерно этот код не компилируют.

Цитата Сообщение от Martmath Посмотреть сообщение
Возможно ли в ТЕЛЕ constexpr функции создать(или изменить существующий constexpr) объект времени компиляции. После, в этом же теле, запихнуть рекурсивно в нее же (ну или, хотя бы, в другую constexpr функцию) данный обьект в качестве входного параметра.
Смотря в каком контексте. Только это опять не описание задачи, а описание того, как вы хотели бы ее решать.
Скорее всего вам не нужны списки объектов, а нужны списки типов.

Цитата Сообщение от Martmath Посмотреть сообщение
Извиняюсь за "мутную" формулировку - насколько я понял, для подобного рода задачи, в возвращаемом в конечной итерации значении должны быть "места" для всех "темповых" переменных используемых в предыдущих итерациях?
Естественно. В этом и заключается ошибочность вашего кода.
Извините, только вот "задачи" опять не видно здесь. Видно набор инструментов, который вы пытаетесь пристроить так и сяк, но непонятно зачем.
2
0 / 0 / 0
Регистрация: 08.08.2014
Сообщений: 21
17.11.2019, 22:44  [ТС] 6
Компилируемость кода каким-то конкретным компилятором еще не означает его работоспособность.
Ок, проверим... (static_assert вроде для этого?)
Видно набор инструментов, который вы пытаетесь пристроить так и сяк
-нуу я в т.ч. учусь на задачах), Соответственно, стараюсь "добить" все возможные пути до конца - пусть даже получив отрицательный результат.

"задачи" опять не видно здесь
-прошу прощения, хотел сам попробовать разобраться: решения указанного "обобщенного" примера/задачи мне бы хватило.....нуу я надеюсь, что хватило)).
Смотря в каком контексте.
О, а в каком контексте это возможно?

Собственно задача, из constexpr массива получить constexpr массив (вектор тоже норм) с уникальными элементами:
...
C++
1
2
constexpr std::array<int, 5>  a = {1,2,2,3,4};
constexpr auto  b = magicVoodooConstexprFunc<a>();//результат: {1,3,4}; auto ==std::array<int, 3> ;magicVoodooConstexprFunс(a)-разумеется тоже пойдет.
0
Вездепух
Эксперт CЭксперт С++
11691 / 6370 / 1723
Регистрация: 18.10.2014
Сообщений: 16,053
17.11.2019, 23:07 7
Цитата Сообщение от Martmath Посмотреть сообщение
Компилятор от микрософт (с выбором с++17 стандарта), если не итерировать - обрабатывает этот код без ошибок.
Это потому, что вы на самом деле не "выбрали стандарт". Чтобы компилятор от Микрософт старался соответствовать стандарту, вам необходимо его об этом попросить. Как минимум выключив нестандартные расширения в настройках проекта и включив "Conformance mode".
0
18833 / 9835 / 2404
Регистрация: 30.01.2014
Сообщений: 17,273
17.11.2019, 23:24 8
Цитата Сообщение от Martmath Посмотреть сообщение
О, а в каком контексте это возможно?
Вот это возможно
Цитата Сообщение от Martmath Посмотреть сообщение
...a pointer type (to object or to function);... " вот собственно "a pointer type to object" и интересен.
когда у нас указатель на объект со статическим классом хранения, например
C++
1
2
3
4
5
6
7
8
9
10
11
struct Tp {};
 
Tp obj;
 
template <Tp * p>
void foo() {}
 
int main()
{
    foo<&obj>();
}
0
0 / 0 / 0
Регистрация: 08.08.2014
Сообщений: 21
17.11.2019, 23:46  [ТС] 9
Извиняюсь, но наверное имеется ввиду static Tp obj; ?
Кстати пробовал делать локальные static обьекты:
C++
1
....static constexpr auto temp = Test{ argtest.test + 1 };....
Как-то не очень то оно отрабатывало (в смысле передавалось далее "вглубь"), хотя мои скромные знания позволяли на это надеяться(.
Глобальные да, глобальные - ок.
0
18833 / 9835 / 2404
Регистрация: 30.01.2014
Сообщений: 17,273
18.11.2019, 00:14 10
Цитата Сообщение от Martmath Посмотреть сообщение
Извиняюсь, но наверное имеется ввиду static Tp obj; ?
static тоже подходит. Но имелось в виду то, что имелось.
Статический класс хранения в С++ у глобальных, статических в классе и статических в функции переменных.
Ознакомьтесь с терминологией.

Цитата Сообщение от Martmath Посмотреть сообщение
Кстати пробовал делать локальные static обьекты
В constexpr функциях это не допускается.

Добавлено через 5 минут
Martmath, я бы на вашем месте не связывался с constexpr объектами, а сделал бы последовательность чисел на базе std::integer_sequence с возможность преобразовать в std::array при надобности
Вроде такого:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template <typename Seq>
struct make_array;
 
template <typename T, T... Vs>
struct make_array<std::integer_sequence<T, Vs...>>
{
    static constexpr T value[] = { Vs... };
};
 
using arr = std::integer_sequence<int, 1, 2, 2, 3, 4>;
 
int main()
{
    for(auto v : make_array<arr>::value)
    {
        std::cout << v << ' ';
    }
}
А манипуляции на этапе компиляции делал бы уже в с типом arr.
0
0 / 0 / 0
Регистрация: 08.08.2014
Сообщений: 21
20.11.2019, 21:55  [ТС] 11
Приветствую. Вроде получилось..возможно даже "стильно, модно, молодежно". Микрософт С++ 17 (vs 2019) со всеми расширениями:
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//Max contribution from Luc Danton, Joel Falcou, Toby Speight, HolyBlackCat. My respect for him.
//https://stackoverflow.com/questions/9644477/how-to-check-whether-a-class-has-specified-nested-class-definition-or-typedef-in
//https://stackoverflow.com/questions/50471075/constexpr-variadic-template-and-unpacking-stdarray 
//https://stackoverflow.com/questions/57131705/how-to-check-if-specific-overload-of-an-operator-exists-at-compile-time-in-c
#include <iostream>
#include <array> 
using namespace std;
constexpr array<int, 5> a = {1,2,2,3,4}; constexpr int b = 5;
 
template <class ...T> class TPack {};
template<class T> using TPackCheckArray =
TPack<typename T::size_type, typename T::value_type, decltype(&T::size)>;
template <class T> using TBracketPointer=const typename T::value_type& (T::*)(typename T::size_type) const noexcept;
 
template<class T, class R = void> struct enable_if_type {typedef R type;}; 
template<class T> using enable_if_type_t =typename enable_if_type<T>::type;
 
template<class T, class Enable = void> struct conditionsArrayTemp : false_type {};
template<class T>struct conditionsArrayTemp
<T, enable_if_type_t <
pair<TPackCheckArray<T>, decltype((TBracketPointer<T>)& T::operator[])>
>>:true_type {};
 
template<class T > constexpr bool conditionsArray = conditionsArrayTemp<T>::value
&& is_integral_v<typename T::size_type>;
template<class T> using TconditionsArray = enable_if_t<conditionsArray<T>>;
template<class T> using TNOconditionsArray = enable_if_t<!conditionsArray<T>>;
 
template <class Tsize, Tsize Size, const auto& Arr, Tsize Index>
constexpr bool indexOnce() {
    for (auto i =0; i != Index; ++i) if (Arr[i] == Arr[Index]) return false;
    for (auto i = Index + 1; i != Size; ++i) if (Arr[i] == Arr[Index]) return false; 
    return true;
}
 
template <class T, class Tsize, class Tvalue, Tsize Size, const T& Arr, Tsize Index = 0, typename... Tpack>
constexpr auto uniqueDataArray(Tpack &&... vpack)   {
    if constexpr (Index==Size) return array<Tvalue, sizeof...(Tpack)>{ forward<Tpack>(vpack)... };
    else {
        if constexpr(indexOnce<Tsize,Size,Arr,Index>()) 
            return uniqueDataArray<T,Tsize, Tvalue, Size, Arr, Index + 1>(forward<Tpack>(vpack)..., Arr[Index]);
        else 
            return uniqueDataArray<T, Tsize, Tvalue, Size, Arr, Index + 1>(forward<Tpack>(vpack)...);
    }
}
template <typename T, const T& Arr,
/*enable_if_t<conditionsArray<T>,int> v=0*/
TconditionsArray<T>* = nullptr>
constexpr auto uniqueDataArray() {
    return uniqueDataArray<T, typename T::size_type, typename T::value_type, Arr.size(), Arr, 0>();
}
template<typename T, const T& Arr, TNOconditionsArray<T>* = nullptr>
constexpr auto uniqueDataArray() {
    /*static_assert(false, "This is all wrong! U shouldn't be up here!");*/
    return 0;
}
template<typename T,const T Arr> constexpr auto uniqueDataArray() {
    /*static_assert(false,"U go down a dark road, bro!");*/
    return 1;
}
 
#define MAGIC(a) uniqueDataArray<decltype(a),decltype(a)::size_type,decltype(a)::value_type, a.size(), a>();
#define MAGIC1(a) uniqueDataArray<decltype(a),a>();
 
int main() {
    constexpr auto a0 = uniqueDataArray<decltype(a), a>();
    constexpr auto a1 = uniqueDataArray<decltype(b), b>();
    constexpr auto a2 = MAGIC(a);
    constexpr auto a3 = MAGIC1(a);
    constexpr auto a4 = MAGIC1(b);  
    auto r = a1 + a4 + 1;
}
0
20.11.2019, 21:55
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.11.2019, 21:55
Помогаю со студенческими работами здесь

Считать одномерный массив с файла, отсортировать его использую рекурсивный вызов функции
Нужно написать прогу на Си, самую элементарную... Считать одномерный массив с файла, отсортировать...

Вызов constexpr метода, внутри класса в котором метод и объявлен
Есть статический constexpr метод. Есть статическая constexpr же константа, которая инициализируется...

Constexpr функции
В продолжении моего вопроса в этой теме -...

Рекурсивный вызов
Требуется определить функцию: (N,M), которая заполняет прямоугольник, имеющий высоту m, цифрами: n...

рекурсивный вызов мейн
Задача такая: Написать программу содержащую функцию мейн, включить в нее локальную переменную коунт...

Присваивание constexpr к non-constexpr
constexpr float pi = 3.14159265; void some_fun() { float angle = 45.0f*(pi/180.0f); ...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru