cpp-ru / ideas

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

добавить constexpr как модификатор для аргументов функции #415

Closed apolukhin closed 3 years ago

apolukhin commented 3 years ago

Перенос предложения: голоса +22, -0 Автор идеи: Юра Левченко

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

Расмотрим небольшой пример:

test(a, 0);
test(a, 1);
test(a, 2);

int test( int a, constexpr int flag )
{
 switch( flag )
 {
   case 0:
     return a + 1;
   case 1:
     return a - 1;
   case 2:
     return -a;
   default:
     return 0;
 }
}

если второй параметр задать как constexpr, то можно на этапе компиляции создать 3 функции, по аналогии

test<0>(a);
test<1>(a);
test<2>(a);

template<int flag>
int test( int a )
{
 switch( flag )
 {
   case 0:
     return a + 1;
   case 1:
     return a - 1;
   case 2:
     return -a;
   default:
     return 0;
 }
}
apolukhin commented 3 years ago

Antervis, 11 марта 2019, 11:07 и заодно перегрузку по constexpr'ness аргументов, а-ля

bool foo(int i) {
    return true;
}
bool foo(constexpr int i) {
    return false;
}

foo(1); // false
int i;
foo(i); // true

Такое вроде рассматривалось еще к включению в с++11, но комитет решил что сильно многословно получается

yndx-antoshkka, 11 марта 2019, 16:11 Antervis, любая модификация правил перегрузок в 99.999% случаев ведёт к отклонению предложения. Так что лучше подобное не добавлять, и сосредоточиться на базовом функционале.

Antervis, 11 марта 2019, 17:12 yndx-antoshkka, речь же идет не об изменении а о дополнении правил перегрузок. Никакой существующий код в таком случае не пострадает.

Вообще, не хватает языку встроенной семантики pure функций, вот только приделать её походу уже не получится

yndx-antoshkka, 11 марта 2019, 18:20 Antervis, описание правил Overload resolution занимает 21 страницу. Удачи с правками ;)

WPMGPRoSToTeMa, 13 марта 2019, 19:51 Antervis, я думаю куда разумнее будет ввести какой-нибудь maybe_constexpr (или maybe_const), правда нужен ещё какой-нибудь магический механизм в виде constexpr bool std::is_constant(maybe_constexpr const auto& x). В принципе constexpr и maybe_constexpr параметры уже можно эмулировать с помощью аргументов завёрнутых в лямбды и __builtin_constant_p (или другими хаками) для проверки на константность https://godbolt.org/z/Oysrwe. Но с такой эмуляцией конечно проблема в том, что на каждый call-site инстанциируется новый шаблон.

yndx-antoshkka, 11 марта 2019, 16:09 Эта идея обсуждалась, и одна из подгруп была сильно против того, чтобы функция в некоторых случаях неявно становилась шаблонной функцией.

Идея бузусловно стоящая, но надо придумать какой-то аргумент, чтобы успокоить одну из подгруп. Возможно что с недавно принятым terse syntax для концептов (аля void foo(auto SemiRegular val); ), комитет будет не сильно против.

Вообще, основное преимущество подобных аргументов - это возможность делать проверки на этапе компиляции в тех местах, где раньше были только runtime:

int array<int>::at(constepxr usinged index) const {
   try_static_assert(index < size(); std::range_error{"out of range"});
   return __data[index];
}

Юра Левченко, 11 марта 2019, 20:10 yndx-antoshkka, большое спасибо, за ответ! Смотря на тенденцию развития, мне тоже показалось что уже пора вводить такую возможность. Я думаю многие будут благодарны если Вы все таки с второй попытки протолкнете это предложение ;)

Юра Левченко, 12 марта 2019, 12:05 yndx-antoshkka, Добрый день, а хотел бы еще спросить, есть ли возможность как то почитать прошлые отзывы? Ну и совсем наглость, как-то быть подписаным на ответы (ридонли) нового запроса, зарание спасибо!

Игорь Гусаров, 29 января 2020, 19:27 yndx-antoshkka, данное предложение очень помогло бы реализовать оператор [] для кортежей. Тут ведь уже были предложения как заменить get(tuple) на более интуитивно понятный tuple[index].

WPMGPRoSToTeMa, 18 марта 2019, 13:36 Кстати, а как это будет сочетаться с эмуляцией именованных аргументов с помощью designated initializers?

Юра Левченко, 21 марта 2019, 13:20 WPMGPRoSToTeMa, А можно подробней? Я просто не помню что бы было принято designated initializers для аргументов функций.

WPMGPRoSToTeMa, 22 марта 2019, 20:47 Юра Левченко,

struct Args {
  int a;
  double b;
  char c;
};

void f(Args);

f({.a = 42, .b = 13.37, .c = 'x'});

Юра Левченко, 11 апреля 2019, 12:50 WPMGPRoSToTeMa, Но здесь у нас один аргумент Args и то что мы передаем это неявное конструирование данного объекта перед тем как передать его в функцию. В данном случае если мы объявим Args как "возможный" constexpr то тогда если все "аргументы" передались как константы то и args будет константный

Виктор Губин, 26 марта 2019, 15:41 У GCC и clang вместо этого введена встроенная функция __builtin_constant_p, в итоге можно делать что-то вроде

constexpr inline __attribute__((always_inline) int foo(int a) noexcept {
     // need inline
    if( __builtin_constant_p(a) ) {
        // some constexpr alg
        return 0;
    } else {
        // some non constexpr alg 
       return 1;
    }
}

Если перегрузку сложно внести в стандарт, неплохо-бы было иметь хотя-бы стандартный оператор проверки на константность аргумента. Скажем что-то вроде:

if( constexpr( a ) ) {
....
}
apolukhin commented 3 years ago

Дубликат #330