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

时间:2017-07-30 14:58:47

标签: c++ boost-program-options

boost::program_options似乎支持某种级别的custom validation,但对我来说似乎很奇怪,验证是根据类型而不是按参数编写的,我想知道我是不是在这里遗漏了什么

例如,假设您有一个“文件编辑”程序,它从命令行获取inputoutput个文件名。接下来假设您要将这些存储到boost::filesystem::path类型的变量中。现在,假设我们要求input文件必须存在,但output文件不存在(即如果output文件不存在存在,我们将创建它。)理想情况下,我们有办法测试input参数是否存在,并且单独表示output文件存在且可写或位于我们可以写信给。 (这里的具体差异实际上并不相关。这适用于您在多个地方使用相同类型的情况,您希望根据用途使用不同的验证规则。)

因为我们通过创建validate的覆盖来配置验证器(可能是在编译时通过类型签名找到的,所以我们只能为boost::filesystem::path的所有实例设置一个验证器。我是看到了notify钩子,但这些回调的签名都有一个const限定符,所以看起来你似乎不能修改这个值,而且在文档中并不清楚throw进入notify回调将进入验证系统。

这似乎是一个非常基本的限制,我认为我可能会遗漏一些东西。我呢?想法?

2 个答案:

答案 0 :(得分: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")
    ;
}

答案 1 :(得分:0)

您可以将每个选项的验证逻辑放入notifier回调中。