c++ - 尝试(稍微)概括 C++ 模板。关联容器 Key:Value Inversion
问题描述
下面的函数模板的目标是使用 any并用 the和倒置unordered_map
生成一个新的。下面的功能适用于. 我希望它另外适用于 EITHER和任何 stl hashmap 模拟。unordered_map
key_type
mapped_type
std::unorderd_map
std::unordered_map
我想维护的另一个好处是,在调用函数时,如果需要默认行为,则auto inversion = InvertHashMap(someIntStringMap)
无需模板参数即可使用。但是,如果我确实提供了有效的初始模板参数,我可以覆盖默认哈希器,例如用于构建反转映射。
我在使容器通用化时遇到了很大的困难,同时仍然提供基于该容器的 5 个模板参数的默认模板参数。一旦我将容器本身作为模板参数,重载解析就会失败,编译也会失败。
我很乐意让关联容器成为唯一的模板参数,但是影响输出容器的模板参数的能力就会丢失,至少在我的非灵活示例中它们可以被显式模板化的方式。
#include <unordered_map>
#include <utility>
#include <functional>
#include <memory>
template <typename InKeyType,
typename InValueType,
typename InHasher,
typename InEq,
typename InAlloc,
typename OutHash = std::hash<InValueType>,
typename OutEq = std::equal_to<InValueType>,
typename OutAlloc=std::allocator<std::pair<constInValueType,InKeyType>>>
std::unordered_map<InValueType, InKeyType, OutHash, OutEq, OutAlloc>
InvertMap(const std::unordered_map<InKeyType, InValueType, InHasher, InEq, InAlloc>& source)
{
std::unordered_map<InValueType, InKeyType, OutHash, OutEq, OutAlloc> outMap;
for (const auto& sourceKVPair : source)
outMap[std::get<1>(sourceKVPair)] = std::get<0>(sourceKVPair);
return outMap;
}
//in a .cpp
unordered_map<int,string> um;
auto newUM = InvertHashMap(um); //works well; newUM::key_type is string
我希望能够打电话InvertMap(aIntStringUnorderedMap)
并且还InvertMap< int, string, hash<int>, ..., MyCustomStringHasher>(aIntStringHashMapLikeClass)//producing a HashMapLikeClass<string,int, MyCustomStringHasher,...defaults>
TLDR:如何在不更改调用站点语义的情况下将争论的容器及其模板参数引入模板?
编辑。这是我尝试将容器用作唯一的模板参数。
template <typename AssocCont>
auto InvertCompliantHashMapThatIsntSTDUnorderedMap(const AssocCont&)
{
typedef typename AssocCont::key_type InKeyType;
typedef typename AssocCont::mapped_type InMappedType;
typedef typename AssocCont::value_type InPairConstruct;
typedef typename AssocCont::hasher InHasher;
typedef typename AssocCont::key_equal InEq;
//...
}
//But now there is no external means of desginating the new container's hasher,equality functor etc...
//And as it turns out, I cant even instantiate a new return object from AssocCont<InKeyType,InMappedType> since it is a distinct and unknown type
AssocCont<InMappedType,InKeyType> outmap = AssocCont<InMappedType,InKeyType>(); // nope. equivalent to object<key,value><otherkey,othervalue>()
双重编辑:在我匆忙提供一个例子时,我选择了std::map
一个备用参数示例,我意识到它没有哈希器,也没有五个模板参数。所以我的问题的基础仍然是试图使这个函数多样化,但特别是对于那些有五个自己的模板参数并且行为兼容的参数...... 我已经编辑了我的帖子以减轻这种疏忽。
解决方案
我觉得这可能以类似于标准算法库的方式更好地实现。换句话说,设计您的反转函数以将一系列迭代器放入输入容器,并将一个迭代器放入输出容器。它将更易于实施并为用户提供更大的灵活性。此外,只要输入和输出迭代器满足某些条件(可能由概念强加),它将在某种程度上独立于容器类型。这是一个示例,它可能不是您想要的,但您可以修改它以满足您的需要:
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <unordered_map>
namespace
{
template <class InputIt, class OutputIt>
void inverse_map(InputIt start, InputIt stop, OutputIt d_first)
{
while(start != stop)
{
*d_first = {start->second, start->first} ;
++d_first ;
++start ;
}
}
} // anonymous namespace
int main()
{
std::map<int, std::string> map_1 {{1, "foo"}, {2, "bar"}, {3, "foo"}} ;
std::unordered_map<std::string, int> map_2 ;
//
// Or, you can use:
//
// std::unordered_map<std::string, int, MyCustomHasher> map_2 ;
//
inverse_map(map_1.begin(), map_1.end(), std::inserter(map_2, map_2.end())) ;
for(const auto& [key, value]: map_2) // requires C++17
std::cout << key << ": " << value << "\n" ;
return 0;
}
输出:
bar: 2
foo: 1
在这里在线试用。
推荐阅读
- excel - 将表格行设置为范围
- scala - 如何使用 scalameta 解析和转换 sbt 项目中的所有源代码文件?
- laravel - 数据未提交到 db laravel:5.8
- rest - Rest:用于提取相似数据的 url 端点
- python - Python face_recognition 处理每一帧耗时太长
- sql - 无法对值进行分组
- python - 有人可以建议如何实现自定义 Django PasswordResetView?
- python - Tensorflow - 时间卷积网络不学习
- git - 如何使用 git checkout 恢复修改过的文件?
- bash - ffmpeg - 如何并行转换大量文件?