2

I'd like to initialize a list of 5-tuples of strings like this:

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 asks why nested initializer lists can't be used for vector of tuples: the answers say to use std::make_tuple. But this makes my code look ridiculous:

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")
  };

If I can't get rid of the std::make_tuple<...>, can I at least use typedef or using to remove the clutter in the code?

using StringQuintet = std::tuple<std::string,std::string,std::string,std::string,std::string>; doesn't help because std::make_tuple<...> needs just the tuples template arguments not the tuple type.

Is there a good way to clean up this boilerplate looking mess?

8
  • 3
    Using explicit template arguments in std::make_tuple defeats its purpose. Just use std::tuple directly. Commented Sep 26, 2018 at 2:57
  • 1
    the point of make_tuple is to deduce types from the initializers, so you don't have to specify the type list Commented Sep 26, 2018 at 2:58
  • 2
    Have you considered array<string, 5> ? Commented Sep 26, 2018 at 2:59
  • 1
    You can use a string operator literal ("/foo"s) Commented Sep 26, 2018 at 3:00
  • 1
    std::make_tuple() is a function it will deduce the types so you don't need to explicitly mention them. Though you will need to use the std::string literal rather than the C-String literal. Commented Sep 26, 2018 at 3:03

2 Answers 2

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

you don't pass types to make tuple.

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

you let the compiler deduce them. Alternatively:

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

to have std string literals (using namespace std::literals; to permit this).

Or:

using StringQuintet = std::tuple<std::string,std::string,std::string,std::string,std::string>;
// ...
StringQuintet("/foo"                 ,"/"           ,"foo"        ,""   ,"foo"),
Sign up to request clarification or add additional context in comments.

Comments

0

Use std::make_tuple:

using namespace std::string_literals;
....

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

....

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.