Я попробовал код ниже в Wandbox:
#include <array>
#include <iostream>
#include <tuple>
#include <typeinfo>
#include <functional>
#include <utility>int main()
{
constexpr std::array<const char, 10> str{"123456789"};
constexpr auto foo = std::apply([](auto... args) constexpr { std::integer_sequence<char, args...>{}; } , str);
std::cout << typeid(foo).name();
}
и компилятор сказал мне, что args...
не постоянное выражение.
В чем дело?
Все функции constexpr должны быть действительны как constexpr, так и нет, даже если отмечен constexpr.
Существует предложение для литерала constexpr, который передает символы в качестве параметров не типового шаблона. затем "hello"_bob
может быть расширен непосредственно на пакет параметров.
Другой подход — вы можете пройти std::integral_constant<T, t>
в лямбду через какой-то механизм, как мой indexer
, Затем преобразование в T
является constexpr, хотя переменная нет. Это не поможет вам с "hello"
в последовательности.
Параметры функции не могут быть помечены constexpr
, Таким образом, вы не можете использовать их в местах, где требуются постоянные выражения, например, нетипизированные аргументы шаблона.
Чтобы сделать то, что вы пытаетесь сделать, потребуется некоторая обработка строки во время компиляции, основанная на аргументах шаблона.
То, что вы хотите, может быть сделано без std::apply
:
#include <array>
#include <iostream>
#include <tuple>
#include <typeinfo>
#include <functional>
#include <utility>
#include <type_traits>
template <std::size_t N, class = std::make_index_sequence<N>>
struct iterate;
template <std::size_t N, std::size_t... Is>
struct iterate<N, std::index_sequence<Is...>> {
template <class Lambda>
constexpr auto operator()(Lambda lambda) {
return lambda(std::integral_constant<std::size_t, Is>{}...);
}
};
int main()
{
constexpr std::array<const char, 10> str{"123456789"};
constexpr auto foo = iterate<str.size()>{}([](auto... is) constexpr { return std::integer_sequence<char, str[is]...>{}; });
std::cout << typeid(foo).name();
}