我有一個人為的例子來說明我想要實作的目標。
#include <tuple>
#include <array>
template <int Val>
struct Value
{
static constexpr auto aValue = Val;
double arbitrary_operation() { return aValue * 2.0; };
};
struct Meta
{
auto do_calculation(std::floating_point auto x) { return x * 4.0; }
};
constexpr auto Values = std::tuple{Value<5>{}, Value<6>{}, Value<7>{}};
constexpr auto ValueMetadata = std::array<std::pair<int, Meta>, 3>{{{5, Meta{}}, {6, Meta{}}, {7, Meta{}}}};
void do_work()
{
std::array<double, ValueMetadata.size()> results;
for (auto& m : ValueMetadata)
{
// find first element in Values tuple that corresponds to parameterized integer (m.first == aValue)
auto value = get_first_element_in_values_tuple<m.first>(); // TODO
// perform arbitrary_operation on that Value and aggregate results
auto arbitrary_value = value.arbitrary_operation();
auto result = m.second.do_calculation(arbitrary_value);
// store in results array
}
}
的主體do_work呈現出一些困難 - 我想知道在編譯時可以在哪里執行。
uj5u.com熱心網友回復:
所以我不確定模板Value類會給你帶來什么。為什么不讓它們成為非模板,那么你可以制作Values一個std::array, 并使用constexprC 20 中的演算法?
無論哪種方式,如果您堅持解決方案,這里是您可以在 C 20演算法的幫助下tuple創建函式的一種方法,并且:tuple_find_ifconstexprstd::index_sequence
template<typename Tuple, typename Func, std::size_t ... N>
consteval auto tuple_find_if_impl(Tuple tup, Func func, std::index_sequence<N...>)
{
constexpr auto compares = std::array{func(std::get<N>(tup))...};
constexpr auto index = std::ranges::find(compares, true) - compares.begin();
return std::get<index>(tup);
}
template<typename ... Ts, typename Func>
consteval auto tuple_find_if(std::tuple<Ts...> tup, Func func)
{
return tuple_find_if_impl(tup, func, std::make_index_sequence<sizeof...(Ts)>{});
}
演示:https ://godbolt.org/z/cEfPoPbdc
這是一個適用于 C 17 的遞回版本:
template<typename T, typename ... Ts, typename Func, std::size_t ... N>
constexpr auto tuple_find_if_impl(std::tuple<T, Ts...> tup, Func func, std::index_sequence<N...>)
{
if constexpr(func(std::get<0>(tup)))
{
return std::get<0>(tup);
}
else
{
return tuple_find_if_impl(std::make_tuple(std::get<N 1>(tup)...), func, std::make_index_sequence<sizeof...(Ts) - 1>{});
}
}
template<typename ... Ts, typename Func>
constexpr auto tuple_find_if(std::tuple<Ts...> tup, Func func)
{
return tuple_find_if_impl(tup, func, std::make_index_sequence<sizeof...(Ts) - 1>{});
}
演示:https ://godbolt.org/z/sc5Txronh
uj5u.com熱心網友回復:
您可以先將 轉換tuple為 anarray并使用std::find來查找合適的索引,然后使用variant對索引進行型別擦除。
#include <algorithm>
#include <variant>
template<std::size_t N>
constexpr auto VarIndexArray = []<std::size_t... Is>(std::index_sequence<Is...>) {
using VarType = std::variant<std::integral_constant<std::size_t, Is>...>;
return std::array{VarType{std::in_place_index<Is>}...};
}(std::make_index_sequence<N>{});
void do_work() {
std::array<double, ValueMetadata.size()> results;
constexpr auto ValueArray = std::apply(
[](auto... vals) { return std::array{decltype(vals)::aValue...}; }, Values);
constexpr auto IndexArray = VarIndexArray<std::tuple_size_v<decltype(Values)>>;
for (auto& m : ValueMetadata) {
// find first element in Values tuple that corresponds to parameterized integer
auto index = std::ranges::find(ValueArray, m.first) - ValueArray.begin();
auto result = std::visit(
[&m](auto index) {
auto arbitrary_value = std::get<index>(Values).arbitrary_operation();
auto result = m.second.do_calculation(arbitrary_value);
return result;
}, IndexArray[index]);
}
}
演示
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/420584.html
標籤:
