如何解决带有嵌套映射的可变参数模板参数推断
在C ++中工作,有时我正在使用嵌套地图。例如,假设:
enum Color { RED,GREEN,BLUE};
enum Shape { CIRCLE,SQUARE,TRIANGLE };
std::unordered_map<Color,std::unordered_map<Shape,int>> shapeColorCount;
对于这些情况,使用可变参数模板来编写以键的类型为模板的setter和getter函数将非常有用。目标将是这样的:
template<typename TValue,typename TKeys...>
TValue& nestedGet(MapTypeHere t_map,const TKeys&... t_keys);
void nestedSet(MapTypeHere t_map,const TValue& t_value,const TKeys&... t_keys);
递归地定义这些函数并不难,但是我的主要问题是使模板参数的类型推断正常工作。问题是指定MapTypeHere。我几乎可以写这样的东西
template<typename TValue,typename TKey>
using Map = std::unordered_map<TKey,TValue>;
template<typename TValue,typename TOuterKey,typename... TInnerKeys>
using Map = std::unordered_map<TOuterKey,Map<TValue,TInnerKeys...>;
template<typename TValue,typename... TKeys>
TValue& nestedGet(Map<TValue,TKeys...>& t_map,const TKeys&... t_keys);
void nestedSet(Map<TValue,const TKeys&... t_keys);
尝试创建递归using指令,但是它抱怨我试图在非包模板变量中尝试使用参数包,而该变量试图为Map
使用基本情况。如果我将它们包装在结构中,似乎允许它使用声明来执行此递归操作,但是然后我遇到了类型推断不起作用的问题。回到上面的示例:
std::unordered_map<Color,int>> shapeColorCount
nestedSet<int,Color,Shape>(shapeColorCount,5,Color::RED,Shape::SQUARE); // This works
nestedSet(shapeColorCount,Shape::SQUARE); // It can't figure out the types for the template
有没有办法使此设置正常工作?
解决方法
是的,您可以编写以下功能:
editor.on('change',(cm,event) => {
editor.execCommand('autocomplete');
});
请注意,此解决方案不依赖于特定的template<typename Map,typename Value,typename FirstKey,typename ...RestKeys>
void nestedSet(Map& map,Value const& value,FirstKey const& key,RestKeys const&... rest_keys)
{
if constexpr(sizeof...(RestKeys) == 0)
map[key] = value;
else
nestedSet(map[key],value,rest_keys...);
}
template<typename Map,typename ...RestKeys>
auto& nestedGet(Map& map,RestKeys const&... rest_keys)
{
if constexpr(sizeof...(RestKeys) == 0)
return map[key];
else
return nestedGet(map[key],rest_keys...);
}
实例化。它适用于键和值类型的任何实例化,以及嵌套的unordered_map<Color,std::unordered_map<Shape,int>>
的任何深度。
这里是demo。
此外,如果您没有c ++ 17,则可以使用带有单个unordered_map
参数的重载模板重写if constexpr
解决方案。
玩太晚了吗?
在我看来,在递归nestedGet()
的情况下,您可以使用if constexpr
(如果可以使用C ++ 17)或如下所示的重载进行编写,
template <typename M,typename K>
auto & nestedGet (M & map,K const & key)
{ return map[key]; }
template <typename M,typename K,typename ... RKs>
auto & nestedGet (M & map,K const & key,RKs const & ... rks)
{ return nestedGet(map[key],rks...); }
可以简单地将nestedSet()
函数写在nestedGet()
上
template <typename M,typename V,typename ... Ks>
void nestedSet (M & map,V const & value,Ks const & ... keys)
{ nestedGet(map,keys...) = value; }
以下是完整的编译示例
#include <iostream>
#include <unordered_map>
enum Color { RED,GREEN,BLUE};
enum Shape { CIRCLE,SQUARE,TRIANGLE };
template <typename M,rks...); }
template <typename M,keys...) = value; }
int main ()
{
std::unordered_map<Color,int>> shapeColorCount;
nestedSet(shapeColorCount,42,Color::RED,Shape::SQUARE);
std::cout << nestedGet(shapeColorCount,Shape::SQUARE) << std::endl;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。