Тема constexpr в классах
От: LaptevVV Россия  
Дата: 04.04.26 16:50
Оценка:
Я, конечно, видал разные примеры.
Но вот какой самый примитивный и простой пример можно придумать?
Чтоб без этого вот динамического выделения памяти во время компиляции ?
С конкретными классами (как Страуструп их обзывает) чего-то в голову ничего не приходит...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Отредактировано 04.04.2026 17:36 LaptevVV . Предыдущая версия .
Re: Тема constexpr в классах
От: rg45 СССР  
Дата: 05.04.26 08:28
Оценка: 15 (1)
Здравствуйте, LaptevVV, Вы писали:

LVV>Я, конечно, видал разные примеры.

LVV>Но вот какой самый примитивный и простой пример можно придумать?
LVV>Чтоб без этого вот динамического выделения памяти во время компиляции ?
LVV>С конкретными классами (как Страуструп их обзывает) чего-то в голову ничего не приходит...

1) Любой класс стандатной библиотеки, содержащий статический constexpr член value: is_const, is_pointer, is_object, is_function, is_reference, integral_constant и множество других.

Кстати std::integral_constant допускает использование не только с интегральными типами, но и с любыми типами, объекты которых могут быть использованы как нешаблонные параметры шаблонов, например:

template <auto V> struct Constant : std::integral_constant<decltype(V), V>{};

using pi = Constant<3.14159265359>;
using master_version = Constant<std::array<int, 4>{3,0}>;

struct A {int id{}, double value {};};
using foo = Constant<A{.id = 42, .value = 3.14}>;



2) Конструкторы и функции члены многих классов стандартной библиотеки объявлены constexpr, что позволяет использовать объекты этих классов во время компиляции, например:

static_assert(std::string("12345").size() == 5);


Или я не уловил суть вопроса.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 05.04.2026 9:08 rg45 . Предыдущая версия . Еще …
Отредактировано 05.04.2026 8:59 rg45 . Предыдущая версия .
Отредактировано 05.04.2026 8:50 rg45 . Предыдущая версия .
Re[2]: Тема constexpr в классах
От: LaptevVV Россия  
Дата: 05.04.26 09:25
Оценка:
Спасибо.
R>Или я не уловил суть вопроса.
Я не совсем четко сформулировал.

Попробую снова.
Мне для студентов максимально просто надо.
Вот написал я класс для работы с обыкновенными рациональными дробями (числитель/знаменатель).
Например:
class Fraction              // класс «рациональная дробь»
{  int num {0}, denum{1};           // поля закрыты
   void reduce()                    // закрытый метод
   { int t = std::gcd(num, denum);  // НОД 
     num /= t; denum /= t;          // сокращение
   }
  public:
   Fraction(int num, int denum = 1){
     this->num = num; this->denum = denum;
     reduce();
   }
   Fraction() = default;            // синтезировать
   void print(char last = '\n'){
     std::cout <<"<"<< num <<"/"<< denum <<">"<< last;
   }
};

А как его в constexpr превратить ?
Возможно ли ?
Без шаблонов и прочих сложностей.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: Тема constexpr в классах
От: rg45 СССР  
Дата: 05.04.26 10:31
Оценка: 15 (1)
Здравствуйте, LaptevVV, Вы писали:

LVV>Спасибо.

R>>Или я не уловил суть вопроса.
LVV>Я не совсем четко сформулировал.

LVV>Попробую снова.

LVV>Мне для студентов максимально просто надо.
LVV>Вот написал я класс для работы с обыкновенными рациональными дробями (числитель/знаменатель).
LVV>Например:
LVV>
LVV>class Fraction              // класс «рациональная дробь»
LVV>{  int num {0}, denum{1};           // поля закрыты
LVV>   void reduce()                    // закрытый метод
LVV>   { int t = std::gcd(num, denum);  // НОД 
LVV>     num /= t; denum /= t;          // сокращение
LVV>   }
LVV>  public:
LVV>   Fraction(int num, int denum = 1){
     this->>num = num; this->denum = denum;
LVV>     reduce();
LVV>   }
LVV>   Fraction() = default;            // синтезировать
LVV>   void print(char last = '\n'){
LVV>     std::cout <<"<"<< num <<"/"<< denum <<">"<< last;
LVV>   }
LVV>};
LVV>

LVV>А как его в constexpr превратить ?
LVV>Возможно ли ?
LVV>Без шаблонов и прочих сложностей.

Просто добавляешь constexpr к кострукторам и НЕКОТОРЫМ функциям-членам (собственно подход тот же самый, который используют std::string и многие другие классы стандартной библиотеки):

https://gcc.godbolt.org/z/Y11b8z3hG

class Fraction              // класс «рациональная дробь»
{
   int num{ 0 }, denum{ 1 };           // поля закрыты

   constexpr void reduce() {                    // закрытый метод
      assert(denum != 0);
      int t = std::gcd(num, denum);  // НОД 
      num /= t; denum /= t;          // сокращение
   }
public:
   constexpr Fraction(int num, int denum = 1)
      :  num(num), denum(denum)
   {
      assert(denum != 0);
      reduce();
   }
   constexpr Fraction() = default;            // синтезировать

   constexpr double make_double() const {
      assert(denum != 0);
      return double(num) / denum;
   }
   constexpr explicit operator double() const { return make_double(); }

   void print(char last = '\n') {
      std::cout << "<" << num << "/" << denum << ">" << last;
   }
};


Таким образом, лёгким движением руки объекты Fraction становятся доступны для использования в компайл-тайм:

static_assert(Fraction(3,2).make_double() == 1.5);
static_assert(double(Fraction(3,2)) == 1.5);
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 05.04.2026 10:51 rg45 . Предыдущая версия . Еще …
Отредактировано 05.04.2026 10:44 rg45 . Предыдущая версия .
Отредактировано 05.04.2026 10:39 rg45 . Предыдущая версия .
Re[4]: Тема constexpr в классах
От: LaptevVV Россия  
Дата: 05.04.26 14:16
Оценка:
R>Просто добавляешь constexpr к кострукторам и НЕКОТОРЫМ функциям-членам (собственно подход тот же самый, который используют std::string и многие другие классы стандартной библиотеки):
Понял, спасибо!
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.