// Example program
#include <iostream>
#include <string>
#include <set>
#include <map>
#include <algorithm>
struct cmp {
bool operator()(std::string i, const std::pair<std::string,std::string>& p) const
{
return i < p.first;
}
bool operator()(const std::pair<std::string, std::string>& p, std::string i) const
{
return p.first < i;
}
};
int main(){
std::set<std::string> s1 {"--name", "--id"}; //Conditionally defined mandatory parameters
std::map<std::string, std::string> s2 { {"--name","Admin"}, {"--group","Group1"}}; //options given by user
std::set<std::string> result;
std::set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(),
std::inserter(result, result.end()), cmp());
std::cout << *result.begin();
}
我希望输出是这样的:如果用户错过任何一个强制参数,它应该抛出错误,同时如果用户提到了除强制参数之外的任何额外参数,则错误再次出现预期
set_symmetric_difference也无法使用它。
答案 0 :(得分:2)
它需要能够比较你给它的任何元素组合,包括字符串到字符串和配对。
struct cmp {
bool operator()(const std::string &i1, const std::string &i2)
{
return i1 < i2;
}
bool operator()(const std::pair<std::string, std::string> &p1, const std::pair<std::string, std::string> &p2)
{
return p1.first < p2.first;
}
bool operator()(const std::string &i, const std::pair<std::string, std::string> &p)
{
return i < p.first;
}
bool operator()(const std::pair<std::string, std::string> &p, const std::string &i)
{
return p.first < i;
}
};
输出:
- 编号
来自文档http://en.cppreference.com/w/cpp/algorithm/set_difference
比较函数的签名应等同于以下内容:
bool cmp(const Type1&amp; a,const Type2&amp; b);
签名不需要const&amp;,但是函数对象不能修改传递给它的对象。 类型Type1和Type2必须是类型为InputIt1和InputIt2类型的对象可以取消引用,然后隐式转换为Type1和Type2。
我只用一个比较功能试了一下,但它不起作用。如果我注释掉任何一个函数,它就不起作用。最后一行似乎意味着如果我测试的编译器/ std实现是正确的,那么两个迭代器都必须可以隐式转换为两种类型。但我宁愿只提供所有四种组合。
答案 1 :(得分:1)
您编写的代码在我的计算机上运行on IDEOne。
我查看了C ++规范的工作草案,虽然我没有看到用户提供的比较器的要求会导致行为未定义,但我觉得传递给set_difference的比较器是一个很奇怪的与std :: map和std :: set。
的Compare
模板类型参数不同的类型
如果我正在接近这个问题,我会使用Boost transform_iterator将用户提供的选项映射迭代器映射到std :: string键(选项名称)。见Iterate keys in a C++ map。然后我会使用默认比较器std :: less:
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <boost/iterator/transform_iterator.hpp>
int main(){
std::set<std::string> standard_option_names {"--name", "--id"};
std::map<std::string, std::string> user_supplied_options { {"--name", "Admin"}, {"--group", "Group1"} };
std::set<std::string> different_option_names;
auto get_option_name = [](const std::pair<const std::string, std::string>& p) -> const std::string& {
return p.first;
};
std::set_symmetric_difference(
standard_option_names.cbegin(), standard_option_names.cend(),
boost::make_transform_iterator(user_supplied_options.cbegin(), get_option_name), boost::make_transform_iterator(user_supplied_options.cend(), get_option_name),
std::inserter(different_option_names, different_option_names.end()));
for (const std::string& different_option_name : different_option_names) {
std::cout << different_option_name;
if (standard_option_names.find(different_option_name) == standard_option_names.end()) {
std::cout << " (unknown option)";
} else {
assert(user_supplied_options.find(different_option_name) == user_supplied_options.end());
std::cout << " (mandatory option not supplied)";
}
std::cout << '\n';
}
return EXIT_SUCCESS;
}
结果:
--group (unknown option) --id (mandatory option not supplied)