我想在編譯時通過型別中的值 constexpr 訪問元組元素
#include <iostream>
#include <tuple>
#include <utility>
struct A {
static constexpr int id = 1;
void work() {
std::cout << "A" << std::endl;
}
};
struct B {
static constexpr int id = 2;
void work() {
std::cout << "B" << std::endl;
}
};
int main() {
A a;
B b;
std::tuple<A,B> t = std::make_tuple(a,b);
static constexpr int search_id = 2;
auto& item = std::get< ? ( T::id == search_id ) ? >(t);
item.work();
return 0;
}
我猜使用 std::apply和測驗將是運行時搜索...我使用的是 c 20
uj5u.com熱心網友回復:
您可以使用迭代元組的元素并根據元素型別執行操作,而不是std::get單個元素std::apply
A a;
B b;
auto t = std::make_tuple(a, b);
static constexpr int search_id = 2;
std::apply([](auto&... items) {
([]<class T>(T& item) {
if constexpr (T::id == search_id)
item.work();
}(items), ...);
}, t);
演示
如果你真的想得到一個具有特定id值的元組元素,你仍然可以使用std::apply擴展id所有元素并找到值的偏移量等于search_id作為模板引數std::get
auto& item = std::apply([&t]<class... Args>(const Args&... items) -> auto& {
constexpr auto id = [] {
std::array ids{Args::id...};
return ids.end() - std::ranges::find(ids, search_id);
}();
return std::get<id>(t);
}, t);
item.work();
uj5u.com熱心網友回復:
您可以創建constrexpr函式來獲取索引:
template <typename... Ts>
constexpr std::size_t get_index(int id)
{
constexpr int ids[] = {Ts::id...};
const auto it = std::find(std::begin(ids), std::end(ids), id);
// Handle absent id.
if (it == std::end(ids)) {
throw std::runtime("Invalid id");
}
// You can also possibly handle duplicate ids.
return std::distance(std::begin(ids), it);
}
template <int id, typename... Ts>
constexpr auto& get_item(std::tuple<Ts...>& t)
{
return std::get<get_index<Ts...>(id)>(t);
}
template <int id, typename... Ts>
constexpr const auto& get_item(const std::tuple<Ts...>& t)
{
return std::get<get_index<Ts...>(id)>(t);
}
然后
auto& item = get_item<search_id>(t);
uj5u.com熱心網友回復:
這是 的主要候選物件std::disjunction,可用于執行編譯時線性搜索;您只需要一個輔助型別來充當謂詞:
namespace detail {
template<typename T, auto Id, auto I>
struct get_by_id_pred : std::bool_constant<std::remove_cvref_t<T>::id == Id> {
static constexpr auto index = I;
};
}
template<int Id>
constexpr auto&& get_by_id(auto&& t) noexcept {
using tuple_t = std::remove_cvref_t<decltype(t)>;
return [&]<auto ...Is>(std::index_sequence<Is...>) -> auto&& {
using res = std::disjunction<
detail::get_by_id_pred<std::tuple_element_t<Is, tuple_t>, Id, Is>...
>;
static_assert(res::value, "id not found");
return std::get<res::index>(decltype(t)(t));
}(std::make_index_sequence<std::tuple_size_v<tuple_t>>{});
}
...
auto& item = get_by_id<search_id>(t);
Online Demo
uj5u.com熱心網友回復:
我對這一行感到困惑:
static constexpr int search_id = 2;
它的目的是什么?
請注意,使用型別別名以干凈的方式解決問題,您仍然可以獲得id價值:
int main() {
A a;
B b;
std::tuple<A,B> t = std::make_tuple(a,b);
using search = B;
auto& item = std::get<search>(t);
item.work();
std::cout << search::id << '\n';
return 0;
}
https://godbolt.org/z/se5jxMWdv
另請注意,代碼更易于維護,沒有神奇的價值2。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/440080.html
下一篇:在div內移動所有具有類的元素
