如果未找到映射条目,则返回特定的映射条目而不是 map::end

Return specific map entry instead of map::end if no map entry was found

本文关键字:映射 end map 返回 如果      更新时间:2023-10-16

在 switch 语句中,如果其他情况都不适用,则可以指定默认返回值。我想对 std::map 做类似的事情,但我不确定是否有可能:如果没有键适合搜索,我可以让地图返回特定的值/条目而不是 map::end 吗?

示例(这是我最终想做的 - 我知道代码不起作用):

std::map<std::string, void* (*) (DataObject*)> commands; //Mapping functions to keys
commands["Test"] = function(DataObject d){doSomething();}
commands[Nothing else applies] = function(DataObject d){doSomethingElse();}
commands.find("Test")(someDataObject); // doSomething(); happens
commands.find("blabla")(someDataObject); //doSomethingElse(); happens because no other entry was found

这样的事情可能吗?

(另外,我在这个例子中使用函数指针的方式可能根本不起作用 - 我可以使用 cpp11 的 lambda 表达式来完成我想做的事情吗?

我不想使用开关子句,也不想要if(m.find(x) != m.end())子句,也不想要更多 if-else。

您可以使用自己的函子和默认值:

struct MyFunctor: public std::function<void(DataObject*)> {
    template <typename F>
    MyFunctor (F &&f) : std::function<void(DataObject*)> (std::forward<F> (f)) { }
    MyFunctor () : std::function<void(DataObject*)> (doSomethingElse) { }
};

假设doSomethingElse是一个已经定义的函数。

然后你可以简单地做:

std::map<std::string, MyFunctor> commands; //Mapping functions to keys
commands["Test"] = [] (DataObject *) { }; // Assign from lambda
DataObject *myDataObject= new DataObject();
commands["Not Defined"] (myDataObject); // Call doSomethingElse

您可以使用模板轻松获得不同的默认值(在编译时定义MyFunctor

template <void (*DefaultFn) (DataObject*)>
struct MyFunctor: public std::function<void(DataObject*)> {
    template <typename F>
    MyFunctor (F &&f) : std::function<void(DataObject*)> (std::forward<F> (f)) { }
    MyFunctor () : std::function<void(DataObject*)> (DefaultFn) { }
};
std::map<std::string, MyFunctor<doSomethingElse>> commands;

不,您不能在std::map中使用该功能,因为当找不到键时std::map::find()返回等于 end() 的迭代器,并且您无法取消引用它。因此,您要么需要使用if( m.find( "blah" ) == m.end() )子句,要么使用其他std::map的东西,或者使用所需的功能编写自己的类。

您可能具有特殊的值类型,其默认状态将具有您需要的功能,然后通过std::map::operator[]而不是std::map::find()但会产生副作用来访问它 - 对于您搜索的每个键,新条目将被添加到地图中。我怀疑这比有一个if()条款更好的解决方案,但这取决于你。