C++ template type_trait enable_if a class 是一个map
C++ template type_trait enable_if a class is a map
#include <iostream>
#include <any>
#include <vector>
#include <map>
#include <unordered_map>
#include <string>
using namespace std;
// enable_if_t = MapType implements .find(KeyType key), .begin(), .end(), and .begin()
// and MapType::iterator it has it->first and it->second
template<typename MapType>
decltype(declval<MapType>().begin()->second) MapGetOrDefault(
MapType mymap,
decltype(declval<MapType>().begin()->first) key,
decltype(declval<MapType>().begin()->second) defaultValue = decltype(declval<MapType>().begin()->second){}
)
{
auto it = mymap.find(key);
if (it!=mymap.end()) return it->second;
else return defaultValue;
}
int main()
{
map<string, int> a;
unordered_map<int, string> b;
a["1"] = 2;
cout << MapGetOrDefault(a, "1") << " " << MapGetOrDefault(a, "2") << " " << MapGetOrDefault(a, "2", -1) << "\n";
b[1] = "hello";
cout << MapGetOrDefault(b, 1) << " " << MapGetOrDefault(b, 2) << " " << MapGetOrDefault(b, 3, "world") << "\n";
return 0;
}
我正在尝试创建一个可用于所有类型地图的通用 get_or_default()
函数。 class 必须满足 4 个条件才能算作地图,如代码注释中所示。
我如何使用 C++ 类型特征来做到这一点?另外,如何将 decltype(declval<MapType>().begin()->first)
改成更干净的东西?
编辑:在这种情况下还需要 enable_if_t
吗?我的目标是防止编译
地图有成员别名 mapped_type
和 key_type
(以及 value_type
),您可以使用它们:
#include <iostream>
#include <any>
#include <vector>
#include <map>
#include <unordered_map>
#include <string>
using namespace std;
template<typename MapType>
typename MapType::mapped_type MapGetOrDefault(
MapType mymap,
typename MapType::key_type key,
typename MapType::mapped_type defaultValue = typename MapType::mapped_type{}
)
{
auto it = mymap.find(key);
if (it!=mymap.end()) return it->second;
else return defaultValue;
}
int main()
{
map<string, int> a;
unordered_map<int, string> b;
a["1"] = 2;
cout << MapGetOrDefault(a, "1") << " " << MapGetOrDefault(a, "2") << " " << MapGetOrDefault(a, "2", -1) << "\n";
b[1] = "hello";
cout << MapGetOrDefault(b, 1) << " " << MapGetOrDefault(b, 2) << " " << MapGetOrDefault(b, 3, "world") << "\n";
return 0;
}
模板别名有助于获得更简洁的语法:
template <typename T> using mapped_type = typename T::mapped_type;
template <typename T> using key_type = typename T::key_type;
template<typename MapType>
mapped_type<MapType> MapGetOrDefault(
MapType mymap,
key_type<MapType> key,
mapped_type<MapType> defaultValue = mapped_type<MapType>{}
)
{
auto it = mymap.find(key);
if (it!=mymap.end()) return it->second;
else return defaultValue;
}
PS:我没有更改它,因为它不是问题的一部分,但是在将它传递给函数时不应该复制地图,而是使用 const MapType& mymap
参数。
PPS:正如 Caleth 在评论中提到的,使用透明比较器,即具有 Comparator::is_transparent
成员类型的比较器,您可能希望支持此处列出的重载 (4) : https://en.cppreference.com/w/cpp/container/map/find 通过引入另一个模板参数 KeyType
可以从 key
参数推导出来。
#include <iostream>
#include <any>
#include <vector>
#include <map>
#include <unordered_map>
#include <string>
using namespace std;
// enable_if_t = MapType implements .find(KeyType key), .begin(), .end(), and .begin()
// and MapType::iterator it has it->first and it->second
template<typename MapType>
decltype(declval<MapType>().begin()->second) MapGetOrDefault(
MapType mymap,
decltype(declval<MapType>().begin()->first) key,
decltype(declval<MapType>().begin()->second) defaultValue = decltype(declval<MapType>().begin()->second){}
)
{
auto it = mymap.find(key);
if (it!=mymap.end()) return it->second;
else return defaultValue;
}
int main()
{
map<string, int> a;
unordered_map<int, string> b;
a["1"] = 2;
cout << MapGetOrDefault(a, "1") << " " << MapGetOrDefault(a, "2") << " " << MapGetOrDefault(a, "2", -1) << "\n";
b[1] = "hello";
cout << MapGetOrDefault(b, 1) << " " << MapGetOrDefault(b, 2) << " " << MapGetOrDefault(b, 3, "world") << "\n";
return 0;
}
我正在尝试创建一个可用于所有类型地图的通用 get_or_default()
函数。 class 必须满足 4 个条件才能算作地图,如代码注释中所示。
我如何使用 C++ 类型特征来做到这一点?另外,如何将 decltype(declval<MapType>().begin()->first)
改成更干净的东西?
编辑:在这种情况下还需要 enable_if_t
吗?我的目标是防止编译
地图有成员别名 mapped_type
和 key_type
(以及 value_type
),您可以使用它们:
#include <iostream>
#include <any>
#include <vector>
#include <map>
#include <unordered_map>
#include <string>
using namespace std;
template<typename MapType>
typename MapType::mapped_type MapGetOrDefault(
MapType mymap,
typename MapType::key_type key,
typename MapType::mapped_type defaultValue = typename MapType::mapped_type{}
)
{
auto it = mymap.find(key);
if (it!=mymap.end()) return it->second;
else return defaultValue;
}
int main()
{
map<string, int> a;
unordered_map<int, string> b;
a["1"] = 2;
cout << MapGetOrDefault(a, "1") << " " << MapGetOrDefault(a, "2") << " " << MapGetOrDefault(a, "2", -1) << "\n";
b[1] = "hello";
cout << MapGetOrDefault(b, 1) << " " << MapGetOrDefault(b, 2) << " " << MapGetOrDefault(b, 3, "world") << "\n";
return 0;
}
模板别名有助于获得更简洁的语法:
template <typename T> using mapped_type = typename T::mapped_type;
template <typename T> using key_type = typename T::key_type;
template<typename MapType>
mapped_type<MapType> MapGetOrDefault(
MapType mymap,
key_type<MapType> key,
mapped_type<MapType> defaultValue = mapped_type<MapType>{}
)
{
auto it = mymap.find(key);
if (it!=mymap.end()) return it->second;
else return defaultValue;
}
PS:我没有更改它,因为它不是问题的一部分,但是在将它传递给函数时不应该复制地图,而是使用 const MapType& mymap
参数。
PPS:正如 Caleth 在评论中提到的,使用透明比较器,即具有 Comparator::is_transparent
成员类型的比较器,您可能希望支持此处列出的重载 (4) : https://en.cppreference.com/w/cpp/container/map/find 通过引入另一个模板参数 KeyType
可以从 key
参数推导出来。