Идиоматический способ обеспечения совместимости функций constexpr - PullRequest
0 голосов
/ 25 мая 2018

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

#include <tuple>
void blah();
int buh;

constexpr auto get() 
{ 
    return std::get<0>(std::make_tuple(&blah, &buh));
}

int main()
{
    get();
}

Можно было бы ожидать, что, поскольку функция get() является константным выражением, она вернет константу.

Это не то, что происходит: std::make_tuple, std::get создаются и называются: https://godbolt.org/g/PkHrTp

Теперь, если мы заменим реализацию get() на

constexpr auto get() 
{ 
    constexpr auto x = std::get<0>(std::make_tuple(&blah, &buh));
    return x;
}

Мы получим ожидаемыйповедение: вычисление параметра x оптимизировано, даже при -O0, и make_tuple, get не создаются, что может быть довольно полезно для уменьшения двоичного раздувания.

Есть лиидиоматический способ обеспечить, чтобы функции вида constexpr auto foo() всегда вели себя так, как во втором примере?

А сейчас я бы прибегнул к:

#define constexpr_return(X) do { constexpr auto constexpr_return_x_ = X; return constexpr_return_x_; } while(0)

constexpr_return(std::get<0>(std::make_tuple(&blah, &buh)));

например, но я не знаюесли это оптимально.

1 Ответ

0 голосов
/ 26 мая 2018
template<auto x>
std::integral_constant< std::decay_t<decltype(x)>, x > k{};

параметры шаблона нетипичного типа должны практически оцениваться во время компиляции.

k<get()> или в определенных угловых случаях k<get()>(), вероятно, делает то, что вы хотите.

Это нене работает для constexpr значений, которые не могут быть переданы как нетиповые параметры шаблона, но это работает для целых чисел и указателей и указателей на функции.

...