我试图实现某种使用编译时字符串作为键(该对的第一个元素)的映射(一对元组)。所以我想使用这个answer,但是我的代码存在问题:字符串在一对内。
#include <type_traits>
#include <tuple>
namespace meta {
template < typename T >
struct CType { using type = T; };
namespace detail {
template <typename T>
struct typeid_t {
using type = typename std::remove_cv<
typename std::remove_reference<T>::type
>::type;
};
}
template <typename T>
constexpr decltype(auto) typeid_(T&&) {
return CType<typename detail::typeid_t<T>::type>{};
}
}
struct HashConstString {
using value_type = uint32_t;
static constexpr uint32_t hash(const char* str) {
return str[0];
}
};
template < typename T_Hash,
typename... T_Pairs >
class UniversalMap {
template < typename T_Pair >
using U_Pair = decltype(std::make_pair(
std::integral_constant<typename T_Hash::value_type, T_Hash::hash(std::get<0>(T_Pair{}))>{},
typename decltype(meta::typeid_(std::get<1>(T_Pair{})))::type {}
));
using U_Map = decltype(std::make_tuple(
U_Pair<T_Pairs>{}...
));
private:
U_Map m_map;
};
template < typename T_Hash,
typename... T_Pairs >
constexpr decltype(auto) make_UniversalMap(T_Hash hash, T_Pairs... pairs) {
(void)hash;
((void)pairs,...);
return UniversalMap<T_Hash, T_Pairs...>();
}
int main() {
constexpr auto hashValue = HashConstString::hash("Test");
constexpr auto map = make_UniversalMap(HashConstString{},
std::make_pair("Test", meta::CType<int>{})
);
}
所以我不知道当字符串已经在字符串中时如何正确地散列字符串。因为std :: get给了我一个引用,这似乎是我有一个解除引用的空指针错误的原因。
是否有一些&#34;技巧&#34;在创建配对之前不必计算哈希就可以完成这项工作吗?
答案 0 :(得分:1)
问题不在于std::get
,而在于您创建了const char*
的元组。当"Test"
作为参数传递给const char*
时,make_pair
会衰减到std::pair<const char[5], int>
。不幸的是,显式指定对模板参数(例如std::array
)不起作用,因为您无法创建类型为array的std容器。
相当尴尬的解决方案是使用struct HashConstString
{
using value_type = uint32_t;
static constexpr uint32_t hash(const char *str) { return str[0]; }
// add this overload
template <std::size_t N>
static constexpr uint32_t hash(std::array<char, N> str) { return str[0]; }
};
:
constexpr auto map = make_UniversalMap(HashConstString{},
std::make_pair(std::array<char, 5>{"Test"}, int{}));
然后像这样打电话:
std::array
为避免指定template <std::size_t N> constexpr auto make_strarray(const char(&str)[N])
{
// unfortunately std::array<char, N>{str} does not work :(
std::array<char, N> arr{};
for (std::size_t i = 0; i < N; ++i)
arr[i] = str[i];
return arr;
}
的大小,您可以创建辅助函数:
C++20
或者在std::copy
template <std::size_t N> constexpr auto make_strarray(const char(&str)[N])
{
std::array<char, N> arr{};
std::copy(str, str + N, arr.begin());
return arr;
}
看起来brew uninstall --ignore-dependencies --force python python@2
unset PYTHONPATH
brew install python python@2
将成为constexpr:
pip