Информация об изменениях

Сообщение Re[3]: Тема constexpr в классах от 05.04.2026 10:31

Изменено 05.04.2026 10:51 rg45

Re[3]: Тема constexpr в классах
Здравствуйте, 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);
Re[3]: Тема constexpr в классах
Здравствуйте, 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);