如何计算 std::for_each lambda 函数所需的类型
Posted
技术标签:
【中文标题】如何计算 std::for_each lambda 函数所需的类型【英文标题】:How to work out types required for std::for_each lambda function 【发布时间】:2017-01-15 13:10:32 【问题描述】:我对如何确定在 std::for_each 中使用 lambda 函数所需的类型感到困惑。在这种情况下,我似乎不能使用 auto 作为参数(Visual Studio 2013 无论如何都会抱怨)。
在下面的代码中,我原以为我会使用 section 作为 for_each 函数的类型,但实际上我必须使用
const std::pair<std::string, std::unordered_map<std::string, std::string> >
对于这种情况下的“内部”类型,我应该使用什么?
我的主要问题是如何确定使用哪种类型?
#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
// key=value pairs within a section
typedef std::unordered_map<std::string, std::string> keyvalue;
// [section1] - top level
typedef std::unordered_map< std::string, std::unordered_map<std::string, std::string> > sections;
class config
public:
config()
setup();
typedef sections::iterator iterator;
iterator begin() return sections_.begin();
iterator end() return sections_.end();
private:
sections sections_;
void setup()
// obviously we wouldn't hard code like this in a real program
sections_["programming languages"].insert(std::make_pair("C", "imperative"));
sections_["programming languages"].insert(std::make_pair("C++", "OOP"));
sections_["programming languages"].insert(std::make_pair("Java", "OOP"));
sections_["programming languages"].insert(std::make_pair("Haskell", "functional"));
sections_["programming languages"].insert(std::make_pair("Prolog", "logic"));
;
int main()
config cfg;
std::for_each(cfg.begin(), cfg.end(), [](const std::pair<std::string, std::unordered_map<std::string, std::string> > sec)
std::cout << "section name: " << sec.first << std::endl;
// what is inner type - thought it would be keyvalue ???
//std::for_each(sec.second.begin(), sec.second.end(), [](const keyvalue& pr)
//std::cout << "first: " << pr << std::endl;
//);
);
// I thought type would be sections ???
//std::for_each(cfg.begin(), cfg.end(), [](const sections& sec)
// std::cout << "section name: " << sec.first << std::endl;
//);
【问题讨论】:
你为什么不用for (auto &&sec : cfg)
?
【参考方案1】:
你也可以像这样使用decltype
:
config cfg;
std::for_each(cfg.begin(), cfg.end(), [](const decltype(*cfg.begin())& sec)
std::cout << "section name: " << sec.first << std::endl;
std::for_each(sec.second.begin(), sec.second.end(), [](const decltype(*sec.second.begin())& pr)
std::cout << "first: " << pr.first << std::endl;
);
);
我不能 100% 确定引用类型对此有何影响,因此删除它可能更合适,例如 const std::remove_reference<decltype(*cfg.begin())>::type& sec
虽然需要注意的是VS2013 ItelliSense在decltype方面存在问题,即使编译正常也会标记为错误。
STL 容器总是定义一个value_type
,所以在这种情况下,您可以使用decltype(inst)::value_type
,并且不需要remove_reference 恶作剧。所以我建议你也像这样在你的类型中添加一个value_type
typedef:
class config
public:
typedef sections::value_type value_type;
那么你可以这样做:
config cfg;
std::for_each(cfg.begin(), cfg.end(), [](const decltype(cfg)::value_type& sec)
std::cout << "section name: " << sec.first << std::endl;
std::for_each(sec.second.begin(), sec.second.end(), [](const decltype(sec.second)::value_type& pr)
std::cout << "first: " << pr.first << std::endl;
);
);
【讨论】:
以上是关于如何计算 std::for_each lambda 函数所需的类型的主要内容,如果未能解决你的问题,请参考以下文章
C++ STL应用与实现26: 如何使用std::for_each以及基于范围的for循环 (since C++11)
地图的 std::for_each() 给出无效的初始化错误
std::for_each 和 std::vector 析构函数调用