我希望構建一個編譯時只讀映射,并希望用 astd::array或std::tuple每個元素是std::pair. 為了便于使用,我想避免在構造時注釋每個條目,我希望它推斷出地圖中的元素數量,即:
constexpr MyMap<int, std::string_view> my_map{
{1, "value1"},
{2, "value2"},
};
我已經嘗試了許多策略來做到這一點,但我似乎陷入了制作一個能夠接受任意數量元素并告訴編譯器所有括號條目正在傳遞(例如{1, "value1"}) 是一對,否則無法推匯出型別。
例如:
template <typename Key, typename Mapped, typename... Args>
constexpr auto make_map(std::pair<Key, Mapped>&& first, Args&&... args) {
if constexpr (sizeof...(Args) == 0) {
return std::tuple{std::forward<decltype(first)>(first)};
}
return std::tuple_cat(
std::tuple{std::forward<decltype(first)>(first)},
make_map(std::forward<Args>(args)...)
);
}
似乎我可以制作一個宏,它可以讓我快速地為所有引數制作函式的版本,直到一個合理的數字(比如 10-15),但這感覺更丑陋和更糟。
有沒有辦法做我想做的事,還是我需要求助于宏或讓用戶用 注釋每個條目std::pair?
uj5u.com熱心網友回復:
如果我理解正確,地圖的大小是已知的并且是固定的?如果是這樣,為什么不使用常規的 c 樣式陣列建構式?不幸的是,沒有辦法讓編譯器推匯出直接初始化串列的型別(例如:推導{1, "value"}到std::pair<int, std::string_view>),因此,您必須指定推導作業的型別。
#include <array>
#include <string_view>
#include <utility>
template <typename K, typename V, size_t N>
class MyMap {
public:
using value_type = std::pair<K, V>;
constexpr explicit MyMap(value_type(&&init)[N])
: data_(std::to_array(std::forward<value_type[N]>(init))) {}
const std::array<value_type, N> data_;
};
template <typename K, typename V, size_t N>
constexpr MyMap<K, V, N> MakeMyMap(
typename MyMap<K, V, N>::value_type(&&init)[N]) {
return MyMap{std::forward<typename MyMap<K, V, N>::value_type[N]>(init)};
}
int main(int argc, char* argv[]) {
constexpr std::string_view value_1 = "value1";
constexpr std::string_view value_2 = "value2";
constexpr auto my_map = MakeMyMap<int, std::string_view>({
{1, value_1},
{2, value_2},
});
static_assert(my_map.data_.at(0) == std::make_pair(1, value_1));
static_assert(my_map.data_.at(1) == std::make_pair(2, value_2));
return EXIT_SUCCESS;
}
注意:這c 20只是因為std::to_array(https://en.cppreference.com/w/cpp/container/array/to_array)。但是人們可以很容易地實作這一點c 17
#include <array>
#include <cstddef>
#include <type_traits>
#include <utility>
namespace internal {
template <bool Move = false, typename T, std::size_t... I>
constexpr std::array<std::remove_cv_t<T>, sizeof...(I)> to_array_impl(T (&a)[sizeof...(I)], std::index_sequence<I...>) {
if constexpr (Move) {
return {{std::move(a[I])...}};
} else {
return {{a[I]...}};
}
}
} // namespace internal
template <typename T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N]) noexcept(
std::is_nothrow_constructible_v<T, T&>) {
static_assert(!std::is_array_v<T>);
static_assert(std::is_constructible_v<T, T&>);
return internal::to_array_impl(a, std::make_index_sequence<N>{});
}
template <typename T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T(&&a)[N]) noexcept(
std::is_nothrow_move_constructible_v<T>) {
static_assert(!std::is_array_v<T>);
static_assert(std::is_move_constructible_v<T>);
return internal::to_array_impl<true>(a, std::make_index_sequence<N>{});
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/380300.html
上一篇:C 模板的部分特化,沒有代碼重復
