cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
89 stars 0 forks source link

constexpr(expr) - альтернативный синтаксис "constexpr!" для функции и const(auto) #321

Open apolukhin opened 3 years ago

apolukhin commented 3 years ago

Перенос предложения: голоса +2, -3 Автор идеи: Данил Луценко

Разрешить условное выражение этапа компиляции после ключевого слова constexpr. Если выражение вычисляется как true, то функция вычисляется только на этапе компиляции, если false - только (!) этапе исполнения

Позволяет явно указывать возможность исполнения функции на этапе компиляции добавляя гибкость для мета-программирования, и имеет более привычный синтаксис (подобный уже используется для noexcept(expr) и decltype(expr)) нежели "constexpr!".

Например,

template<typename T>
constexpr T ConstValue = static_cast<T>(0x1'000'000);

constexpr(false == false) int A() { return 5; }
constexpr(true == false) int B() { return 5; }

static_assert(A() == 5); //ОК, функция помечена как constexpr(true)
static_assert(B() == 5); //ошибка, функция не может использоваться на этапе компиляции

int main()
{
    assert(A() == 5); //ошибка, функция A не может вызываться на этапе исполнения
    assert(B() == 5); //ОК
}

Предлагаю так же разрешить constexpr(auto), который ведет себя как и текущий constexpr

constexpr(auto) int A() { return 5; }

В будущем предлагаю помечать неявно как constexpr(auto) любую inline функцию или метод, которому может примениться constexpr, что позволит частично использовать уже написанный код на этапе исполнения без потери совместимости с существуещим кодом использующим constexpr.

Почему для constexpr(false) не задействовать старый синтаксис вместо constexpr(auto)?! Предлагаю в будущем добавить в объявление функции const(expr)/const(auto), где const(auto) генерирует 2 функции, одна с const модификатором, вторая без. Ровно как и constexpr(auto), который генерирует 2 функции, одну для этапа компиляции, вторую для исполнения.

const(auto) может использоваться в следующем случае

class A {
    std::string m;
public:
    auto& get_m() const(auto) { return m; }
};

что аналогично следующему коду

class A {
    std::string m;
public:
    auto& get_m() { return m; }
    auto& get_m() const { return m; }
};

Как и в случае с constexpr(auto), предлагаю помечать неявно const(auto) все inline методы, которые могут быть помечены как const, что избавит от забытых const в библиотечном коде без потери совместимости со старым кодом. Возможность явно указывать константность в const с помощью условного выражения этапа компиляции позволит управлять константностью метода исходя из параметров шаблона и для явного описания константности в интерфейсе.

apolukhin commented 3 years ago

Данил Луценко, 9 июля 2018, 22:44 Дополнительно предлагаю разрешить перегрузку функции для контекстов времени компиляции и исполнения, как альтернатива магической std::is_constant_evaluated

constexpr(false) int atoi(const char *S);
constexpr(true) int atoi(const char *S) { /*...*/ }
static_assert(atoi("5") == 5); //Вызывает constexpr(true) int atoi(const char *S)
int main()
{
    assert(atoi("5") == 5); //Вызывает constexpr(false) int atoi(const char *S)
}

тогда constexpr(auto) можно сделать лучше:

Например пусть следующий код

constexpr(auto) int atoi(const char *c)
{
    return std::atoi(c);
}

аналогичен следующему коду

constexpr(false) int atoi(const char *c)
{
    return std::atof(c);
}

т.к. нет перегрузки функции std::atoi c constexpr(true)

И

consexpr(auto) int atoi(const char *S) {

   int result = 0;
   while (*S) {
      result = result * 10 + (*S - '0');
      ++S;
   }
   return result;
}

аналогичен следующему,

consexpr(false) int atoi(const char *S) {
   int result = 0;
   while (*S) {
      result = result * 10 + (*S - '0');
      ++S;
   }
   return result;
}
consexpr(true) int atoi(const char *S) {
   int result = 0;
   while (*S) {
      result = result * 10 + (*S - '0');
      ++S;
   }
   return result;
}

т.к. функция может быть выполнена на этапе компиляции

Fihtangolz, 17 июля 2018, 20:50 constexpr! <- давайте без ! как нибудь constexpr_hard

apolukhin commented 3 years ago

А зачем это нужно? Есть реальный пример, где constexpr(false) и constexpr(true) действительно полезны?