Как определить, есть ли функция func. является constexpr? и отметить другую функцию. constexpr в зависимости от этого?
Предполагая, что у меня есть некоторый шаблон функции f1:
template<typename f2>
int f1(int i, int j) noexcept {
return i + j + f2(i, j);
}
существует ли способ определить, может ли f2(i, j)
быть constexpr
. (независимо от того, является ли это функтором или функтором), и поэтому отметьте f1<f2>
как constexpr
тоже?
Я думаю использовать SFINAE здесь как-то, но не нашел, как обнаружить constexpr
с помощью свойств типа
Ответы
Ответ 1
Вы можете пометить f1
как constexpr
.
template<typename f2>
constexpr int f1(int i, int j) noexcept {
return i + j + f2(i, j);
}
Функция шаблона f1
будет constexpr
iif f2
is.
если f2
нет, вы получите ошибку, только когда используете f1
в выражении постоянной компиляции.
Демо
Ответ 2
Самый простой способ проверить, является ли функция (например, foo
) constexpr
, назначать ее возвращаемое значение на constexpr
, как показано ниже:
constexpr auto i = foo();
если возвращаемое значение не соответствует constexpr
, компиляция завершится с ошибкой.
Если вы хотите, чтобы тест SFINAE проверял, является ли функция (например, foo
) constexpr
, вы можете использовать свойство std::integral_constant
:
std::integral_constant<int, foo()>::value
Live Demo
Ответ 3
Итак, наконец, используя подсказку Jarod42, я напишу и протестировал этот пример:
#include <string>
std::string S = "123567876";
constexpr size_t p() noexcept {
return 10U;
}
template<const size_t = size_t()>
constexpr size_t f(size_t i, size_t j) noexcept {
return std::move(i + j + S.size() + p());
}
#include <iostream>
int main() {
// static constexpr const auto v = f<>(1U, 2U); // error!
std::cout << f(1U, 2U) << "\n";
return 0;
}
теперь он работает правильно, я тестировал его с помощью GCC онлайн, как с С++ 11, так и с C + 14.
Вы можете доказать, что это будет действительно constexpr, если возможно, удалив '+ S.size()':
...
return std::move(i + j + p());
...
и uncommenting значение constexpr:
...
static constexpr const auto v = f(1U, 2U);
std::cout << v << "\n";
...
см. здесь.
Р. С. Спасибо, ребята!