boost::program_options 验证每个参数而不是每个参数类型?

问题描述 投票:0回答:2

boost::program_options
似乎支持某种程度的自定义验证,但对我来说,验证是按照类型而不是按参数编写的,这似乎很奇怪,我想知道我是否在这里遗漏了一些东西。

例如,假设您有一个“文件编辑”程序,它从命令行获取

input
output
文件名。接下来假设您要将这些存储到
boost::filesystem::path
类型的变量中。现在,假设我们要求
input
文件必须存在,但 output
 文件不存在(即,如果 
output
 文件不存在,我们将创建它。)理想情况下,我们有一种方法来测试 
input
 参数是否存在,并且分别测试
output
 文件要么存在并且可写,要么位于我们可以写入的目录中。 (这里的具体差异实际上并不相关。这适用于您在多个地方使用相同类型的任何情况,您希望根据用途有不同的验证规则。)

因为我们通过创建

validate

 的覆盖来配置验证器(大概是在编译时通过其类型签名找到的),所以看来我们只能为 
boost::filesystem::path
 的所有实例拥有一个验证器。我已经看到了 
notify
 钩子,但是这些回调的签名有一个 
const
 限定符,所以看起来你不能修改值,并且文档中并不清楚 
throw
 回调中的 
notify
 如何进入验证系统。

这似乎是一个非常基本的限制,我认为我可能错过了一些东西。我是吗?想法?

c++ boost-program-options
2个回答
1
投票
程序中每个概念有一种类型总是没有坏处的。如果两条路径代表不同的概念,请为它们指定自己的类型:

#include <iostream> #include <cstdlib> #include <boost/program_options.hpp> #include <boost/filesystem.hpp> namespace po = boost::program_options; namespace fs = boost::filesystem; template<class Type, class Tag> struct tagged { Type const& get() const { return value_; } Type& get() { return value_; } operator Type& () { get(); } friend decltype(auto) operator>>(std::istream& is, tagged& t) { return is >> t.get(); } friend decltype(auto) operator<<(std::ostream& os, tagged const& t) { return os << t.get(); } // and so on... Type value_; }; using bar_path = tagged<fs::path, class bar_path_tag>; using foo_path = tagged<fs::path, class foo_path_tag>; int main() { bar_path bar; foo_path foo; po::options_description desc("prog"); desc.add_options() ("foo", po::value(&foo), "a foo path") ("bar", po::value(&bar), "a bar path") ; }
    

0
投票
您可以将每个选项的验证逻辑放入

notifier 回调中。

© www.soinside.com 2019 - 2024. All rights reserved.