如何编写将模板限制为 std::map 和 std::unordered_map 的 C++ 概念
How to write a C++ concept restricting the template to std::map and std::unordered_map
如果我有一个看起来像这样的模板,为了示例而执行简单的复制操作,但对于 std::map
和 std::unordered_map
:
template<typename T1, typename T2>
inline std::map<T1, T2> map_copy(std::map<T1,T2> const& a) {
std::map<T1,T2> output;
output = a;
return output;
}
template<typename T1, typename T2>
inline std::unordered_map<T1, T2> map_copy(std::unordered_map<T1,T2> const& a) {
std::unordered_map<T1,T2> output;
output = a;
return output;
}
有没有办法,可能使用 C++ 概念,将这些定义减少到一个,将可能的类型限制为 std::map
和 std::unordered_map
?
您可以添加约束,
template<template <typename...> class MAP, typename T1, typename T2>
inline MAP<T1, T2> map_copy(MAP<T1,T2> const& a)
requires std::is_same_v<MAP<T1,T2>, std::map<T1,T2>> ||
std::is_same_v<MAP<T1,T2>, std::unordered_map<T1,T2>> {
MAP<T1,T2> output;
output = a;
return output;
}
或者定义一个概念,
template<template <typename...> class MAP, typename T1, typename T2>
concept Mappable = std::is_same_v<MAP<T1,T2>, std::map<T1,T2>> ||
std::is_same_v<MAP<T1,T2>, std::unordered_map<T1,T2>>;
然后
template <template <typename...> class MAP, typename T1, typename T2>
inline MAP<T1, T2> map_copy(MAP<T1,T2> const& a) requires Mappable<MAP, T1, T2> {
MAP<T1,T2> output;
output = a;
return output;
}
您可以使用此概念来检查类型是 std::map
还是 std::unordered_map
:
template<typename T>
concept map_type =
std::same_as<T, std::map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>> ||
std::same_as<T, std::unordered_map<typename T::key_type, typename T::mapped_type, typename T::hasher, typename T::key_equal, typename T::allocator_type>>;
template<map_type T>
T map_copy(T const& a) {
T output;
output = a;
return output;
}
为了通用检查 T
是否是 template<typename...> struct Template;
的实例化,您可以这样做:
template<template<typename...> class Template, typename Class>
struct is_instantiation : std::false_type {};
template<template<typename...> class Template, typename... Args>
struct is_instantiation<Template, Template<Args...>> : std::true_type {};
template<typename Class, template<typename...> class Template>
concept is_instantiation_of = is_instantiation<Template, Class>::value;
template<typename T>
concept map_type =
is_instantiation_of<T, std::map> || is_instantiation_of<T, std::unordered_map>;
template<map_type T>
T map_copy(T const& a) {
T output;
output = a;
return output;
}
template<is_instantiation_of<std::map> T>
T ordered_map_copy(T const& a) {
return a;
}
如果我有一个看起来像这样的模板,为了示例而执行简单的复制操作,但对于 std::map
和 std::unordered_map
:
template<typename T1, typename T2>
inline std::map<T1, T2> map_copy(std::map<T1,T2> const& a) {
std::map<T1,T2> output;
output = a;
return output;
}
template<typename T1, typename T2>
inline std::unordered_map<T1, T2> map_copy(std::unordered_map<T1,T2> const& a) {
std::unordered_map<T1,T2> output;
output = a;
return output;
}
有没有办法,可能使用 C++ 概念,将这些定义减少到一个,将可能的类型限制为 std::map
和 std::unordered_map
?
您可以添加约束,
template<template <typename...> class MAP, typename T1, typename T2>
inline MAP<T1, T2> map_copy(MAP<T1,T2> const& a)
requires std::is_same_v<MAP<T1,T2>, std::map<T1,T2>> ||
std::is_same_v<MAP<T1,T2>, std::unordered_map<T1,T2>> {
MAP<T1,T2> output;
output = a;
return output;
}
或者定义一个概念,
template<template <typename...> class MAP, typename T1, typename T2>
concept Mappable = std::is_same_v<MAP<T1,T2>, std::map<T1,T2>> ||
std::is_same_v<MAP<T1,T2>, std::unordered_map<T1,T2>>;
然后
template <template <typename...> class MAP, typename T1, typename T2>
inline MAP<T1, T2> map_copy(MAP<T1,T2> const& a) requires Mappable<MAP, T1, T2> {
MAP<T1,T2> output;
output = a;
return output;
}
您可以使用此概念来检查类型是 std::map
还是 std::unordered_map
:
template<typename T>
concept map_type =
std::same_as<T, std::map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>> ||
std::same_as<T, std::unordered_map<typename T::key_type, typename T::mapped_type, typename T::hasher, typename T::key_equal, typename T::allocator_type>>;
template<map_type T>
T map_copy(T const& a) {
T output;
output = a;
return output;
}
为了通用检查 T
是否是 template<typename...> struct Template;
的实例化,您可以这样做:
template<template<typename...> class Template, typename Class>
struct is_instantiation : std::false_type {};
template<template<typename...> class Template, typename... Args>
struct is_instantiation<Template, Template<Args...>> : std::true_type {};
template<typename Class, template<typename...> class Template>
concept is_instantiation_of = is_instantiation<Template, Class>::value;
template<typename T>
concept map_type =
is_instantiation_of<T, std::map> || is_instantiation_of<T, std::unordered_map>;
template<map_type T>
T map_copy(T const& a) {
T output;
output = a;
return output;
}
template<is_instantiation_of<std::map> T>
T ordered_map_copy(T const& a) {
return a;
}