如何删除元组初始化向量中的样板文件?

How to remove boilerplate in vector of tuple initialization?

我想像这样初始化一个 5 元组字符串列表:

std::vector<std::tuple<std::string,std::string,std::string,std::string,std::string> >
    examples = 
  {
    {"/foo"                 ,"/"           ,"foo"        ,""   ,"foo"},
    {"/foo/"                ,"/"           ,"foo"        ,""   ,"foo"},
    {"/foo//"               ,"/"           ,"foo"        ,""   ,"foo"},
    {"/foo/./"              ,"/foo"        ,"."          ,""   ,""},
    {"/foo/bar"             ,"/foo"        ,"bar"        ,""   ,"bar"},
    {"/foo/bar."            ,"/foo"        ,"bar."       ,""   ,"bar"},
    {"/foo/bar.txt"         ,"/foo"        ,"bar.txt"    ,"txt","bar"},
    {"/foo/bar.txt.zip"     ,"/foo"        ,"bar.txt.zip","zip","bar.txt"},
    {"/foo/bar.dir/"        ,"/foo"        ,"bar.dir"    ,"dir","bar"},
    {"/foo/bar.dir/file"    ,"/foo/bar.dir","file"       ,""   ,"file"},
    {"/foo/bar.dir/file.txt","/foo/bar.dir","file.txt"   ,"txt","file"}
  };

This question 问为什么嵌套初始化列表不能用于元组向量:答案说使用 std::make_tuple。但这让我的代码看起来很荒谬:

std::vector<std::tuple<std::string,std::string,std::string,std::string,std::string> >
    examples = 
  {
    std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo"                 ,"/"           ,"foo"        ,""   ,"foo"),
    std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo/"                ,"/"           ,"foo"        ,""   ,"foo"),
    std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo//"               ,"/"           ,"foo"        ,""   ,"foo"),
    std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo/./"              ,"/foo"        ,"."          ,""   ,""),
    std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo/bar"             ,"/foo"        ,"bar"        ,""   ,"bar"),
    std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo/bar."            ,"/foo"        ,"bar."       ,""   ,"bar"),
    std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo/bar.txt"         ,"/foo"        ,"bar.txt"    ,"txt","bar"),
    std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo/bar.txt.zip"     ,"/foo"        ,"bar.txt.zip","zip","bar.txt"),
    std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo/bar.dir/"        ,"/foo"        ,"bar.dir"    ,"dir","bar"),
    std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo/bar.dir/file"    ,"/foo/bar.dir","file"       ,""   ,"file"),
    std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo/bar.dir/file.txt","/foo/bar.dir","file.txt"   ,"txt","file")
  };

如果我无法摆脱 std::make_tuple<...>,我可以至少使用 typedefusing 来消除代码中的混乱吗?

using StringQuintet = std::tuple<std::string,std::string,std::string,std::string,std::string>; 没有帮助,因为 std::make_tuple<...> 只需要元组模板参数而不是元组类型。

有什么好的方法可以清理这个看起来一团糟的样板文件吗?

使用std::make_tuple:

using namespace std::string_literals;
....

std::make_tuple("/foo"s                 ,"/"s           ,"foo"s        ,""s   ,"foo"s),

....
 std::make_tuple<std::string,std::string,std::string,std::string,std::string>("/foo"                 ,"/"           ,"foo"        ,""   ,"foo"),

你不传递类型来生成元组。

std::make_tuple("/foo"                 ,"/"           ,"foo"        ,""   ,"foo"),

你让编译器推断它们。或者:

std::make_tuple("/foo"s                 ,"/"s           ,"foo"s        ,""s   ,"foo"s),

具有标准字符串文字(using namespace std::literals; 允许这样做)。

或:

using StringQuintet = std::tuple<std::string,std::string,std::string,std::string,std::string>;
// ...
StringQuintet("/foo"                 ,"/"           ,"foo"        ,""   ,"foo"),