c++ - 区分地图和集合的模板
问题描述
在为、、和创建通用代码时,我需要几个方法,其中处理实际上是不同的。我的问题是让编译器推断出要使用的实现。set
unordered_set
map
unordered_map
考虑这个例子:
#include <map>
#include <unordered_set>
#include <string>
#include <iostream>
using namespace std;
static unordered_set<string> quiet;
static map<const string, const string> noisy;
template <template <typename ...> class Set, typename K>
static void insert(Set<K> &store, const string &key, const string &)
{
cout << __PRETTY_FUNCTION__ << "(" << key << ")\n";
store.insert(key);
}
template <template <typename ...> class Map, typename K, typename V>
static void insert(Map<K, V> &store, const string &key, const string &v)
{
cout << __PRETTY_FUNCTION__ << "(" << key << ", " << v << ")\n";
store.insert(make_pair(key, v));
}
int
main(int, char **)
{
insert(noisy, "cat", "meow");
insert(quiet, "wallaby", ""); /* macropods have no vocal cords */
return 0;
}
尽管 cat-line 有效,但 wallaby-line 会从编译器 (clang-10) 触发以下错误:
t.cc:22:8: error: no matching member function for call to 'insert'
store.insert(make_pair(key, v));
~~~~~~^~~~~~
t.cc:29:2: note: in instantiation of function template specialization
'insert<unordered_set, std::__1::basic_string<char>, std::__1::hash<std::__1::basic_string<char> > >' requested here
insert(quiet, "wallaby", ""); /* macropods have no vocal cords */
该错误很明显,作为quiet
的 ,也unordered_set
被路由到插入实现map
- 而不是为unordered_set
.
现在,这并非完全没有希望——如果我:
- 拼出所有模板参数——包括可选参数(比较器、分配器等)
template <template <typename ...> class Set, typename K, typename A, typename C> static void insert(Set<K, A, C> &store, const string &key, const string &) ... template <template <typename ...> class Map, typename K, typename V, typename A, typename C> static void insert(Map<K, V, A, C> &store, const string &key, const string &v)
- 替换
unordered_set
为set
。
该程序将按预期编译和工作——编译器将set
通过map
每个模板采用的参数数量(三个与四个)来区分。
但是具有与(四个)unordered_set
相同数量的参数......并且有五个参数,所以它不会被路由到地图处理方法......map
unordered_map
如何收紧要由它处理的两种类型的集合处理函数的声明?如何在同一代码中同时处理map
s 和s ?unordered_map
解决方案
insert
您可以使用 SFINAE 技术基本上说:仅当内部调用格式正确时才考虑此重载。例如这样的:
template <template <typename ...> class Set, typename K>
static auto insert(Set<K> &store, const string &key, const string &)
-> std::void_t<decltype(store.insert(key))>
{
cout << __PRETTY_FUNCTION__ << "(" << key << ")" << endl;
store.insert(key);
}
template <template <typename ...> class Map, typename K, typename V>
static auto insert(Map<K, V> &store, const string &key, const string &v)
-> std::void_t<decltype(store.insert(make_pair(key, v)))>
{
cout << __PRETTY_FUNCTION__ << "(" << key << ", " << v << ")" << endl;
store.insert(make_pair(key, v));
}
推荐阅读
- visual-studio-code - 在一行中多次插入相同的文本
- perl - Perl 中的 -p STDIN 是什么意思?
- linux - Podman 失败,在 Fedora 32 上拉取更大的图像
- ruby-on-rails - 如何更新每个 rspec 测试的值?
- linux - 调试时动态链接器(rv64ima-lp64)中的分段错误
- java - 每个配置对象创建单例对象
- python - 适用于崇高文本的系列不适用于 pycharm
- python - 将 5 分钟的时间范围合并为每小时
- c# - 将创建的 zip 文件夹解压缩到同一文件夹?
- javascript - Angular POST 请求在命中 Spring Boot 端点时不起作用