Boost程序选项添加选项语法

26

我正在编写一个使用Boost程序选项库的程序,我注意到以下语法自从我看到它以来一直困扰着我:

desc.add_options()
        ("help","produce help message")
        ( /* other flag, value, description pairs here */)
;

我看到在头文件中,operator()被重载了,但是我不确定它如何使得这个语法是正确的。

其次,除了展示你可以像这样操纵语法之外,与仅调用add_options()多次相比,这种语法有什么优势吗?


11
Boost的作者们喜欢炫耀他们的技能... - Oliver Charlesworth
1
“Haunted”是一个很好的描述……我明白它的正式含义,但感觉有点奇怪…… - thomastiger
2个回答

24
add_options成员函数返回一个options_description_easy_init类型的对象。后者的operator()被重载为返回对自身的引用。这使得你可以像片段中展示的那样链接这些调用。
链式调用和多次调用add_options的区别在于,在前一种情况下,创建了单个options_description_easy_init实例,每次在其上调用operator()时,它都会向拥有者(options_description)添加选项。如果你多次调用add_options,则每次调用都会创建一个新的options_description_easy_init实例。

@paulrehkugler 尼古拉的答案解释了为什么。 - Praetorian

14
优点问题是主观的,但在这种情况下,它是简洁明了的。与我家中某个项目的情况相比较:
("help,h", "Generate this help message")
("output-file,o", po::value<std::string>(), "Output filename. Required.")
("tangent,t", "Generate/load tangent-space basis.")
("collada-output,c", "Write a Collada file, rather than our mesh XML format.")
("arrays,a", "Write arrays instead of indexed verts. Cannot combine with Collada writing.")
("flip-tangent,f", "Change the tangent-space basis matrix's handedness. Negates bitangent.")
("map", po::value<std::string>(), "Map filename. Defaults to the ColladaConv directory's 'stdmap.txt' file.")
("vao", po::value<std::vector<std::string> >(), "Sequence of mappings, of the form:\n"
        "Name # # # #\n"
        "\n"
        "Each # is an attribute index to use for this VAO.\n"
        "Each VAO name must be unique; you cannot use the same VAO in the same place.")

转换为:

visible.add_options()("help,h", "Generate this help message")
visible.add_options()("output-file,o", po::value<std::string>(), "Output filename. Required.")
visible.add_options()("tangent,t", "Generate/load tangent-space basis.");
visible.add_options()("collada-output,c", "Write a Collada file, rather than our mesh XML format.");
visible.add_options()("arrays,a", "Write arrays instead of indexed verts. Cannot combine with Collada writing.");
visible.add_options()("flip-tangent,f", "Change the tangent-space basis matrix's handedness. Negates bitangent.");
visible.add_options()("map", po::value<std::string>(), "Map filename. Defaults to the ColladaConv directory's 'stdmap.txt' file.");
visible.add_options()("vao", po::value<std::vector<std::string> >(), "Sequence of mappings, of the form:\n"
        "Name # # # #\n"
        "\n"
        "Each # is an attribute index to use for this VAO.\n"
        "Each VAO name must be unique; you cannot use the same VAO in the same place.");

代码行的长度很重要。而不需要在每个选项前添加visible.add_options()使得阅读更加容易。


1
我怀疑那是唯一的优点。在我看来,这只是为了让代码更漂亮而做的更多工作。 - paulrehkugler
这两个例子都相当丑陋。你能否定义 options_description_easy_init o = visible.add_options() 并简单地调用 o("help", "Generate this help message"); - Vortico
@Vortico:我并没有看到第一种情况有什么特别不好的地方。实际上,即使你的建议可行,我也不明白它比第一种方法有什么好处。我不知道它是否有效,你需要查看Boost的文档才能确定。但通常来说,保留这样的构造中间结果并不是一个好主意。 - Nicol Bolas
1
@Aconcagua:vao是什么?至少根据当前的语法,每一组括号都清楚地与“add_options”相关。而你的代码则包含了一些奇怪命名的符号。 - Nicol Bolas
我更喜欢非链式选项,因为我的代码格式化程序会尝试将第二个选项中的所有内容放在一行上。 - Roddy
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接