0

Is there a reason std::make_tuple does not accept parameters that are list initialized objects?

#include <string>
#include <map>
#include <cstdint>

class FileInfo
{
public:
    FileInfo() = default;
    FileInfo(const std::string &name, uint64_t size) : mName(name), mSize(size) { }

    bool operator == (const FileInfo& other) const
    {
        return mName == other.mName;
    }

private:
    std::string mName;
    uint64_t mSize = 0;
};

void function(FileInfo fileInfo) { } 

using Modifications = std::map<std::string, std::tuple<std::string, FileInfo, FileInfo>>;

int main(int argc, char *argv[])
{
    Modifications modifications{
        { "f1", std::make_tuple("changed", FileInfo{ "f1", 1 }, FileInfo{ "f1", 2 }) },
        { "f2", std::make_tuple("removed", FileInfo{ "f2", 1 }, FileInfo{}) },
        { "f3", std::make_tuple("added", FileInfo{}, { "f3", 2 }) } // Error
    };

    function({ "f3", 2 }); // OK

    return 0;
}

The third pair from the map gives the following error:

Error C2660 'std::make_tuple': function does not take 3 arguments

This error makes no sense to me. Why does't std::make_tuple accept the third parameter when I explicitly declared the type of Modifications as being std::map<std::string, std::tuple<std::string, FileInfo, FileInfo>>? Is there a compiler limitation or this was simply omitted from standard?

Note: this question is not related to constructing tuple from braced list: initialize-an-stdarray-of-tuples-with-curly-braces

Community
  • 1
  • 1
Alexandru Irimiea
  • 2,513
  • 4
  • 26
  • 46
  • 2
    The problem is that you omitted `FileInfo` from before `{ "f3", 2" }` – M.M Dec 29 '16 at 03:31
  • The type of `Modifications` is irrelevant, `make_tuple(bla,bla,bla)` is an expression that is evaluated independently of whatever you then go on to do with the result of the expression (same as with all expressions in C++) – M.M Dec 29 '16 at 03:33
  • Actually I gave first two entries as examples that work. I omitted on the third one on purpose. The point is, I expected it to work with both `{}` and `FileInfo{}` – Alexandru Irimiea Dec 29 '16 at 03:37

1 Answers1

2

As pointed out in the comments the error is in the fact that you are not constructing the FileInfo object in the call to the make_tuple function, the C++ compiler has no way of knowing what you want the third object to be. If you change the call to something like this

std::make_tuple<std::string, FileInfo, FileInfo>("added", FileInfo{}, { "f3", 2 })

Then also the code will work, you need the make_tuple function to be able to deduce the types of the things in the argument list.

The compiler cannot deduce the type of an initializer list in a template argument

Community
  • 1
  • 1
Curious
  • 20,870
  • 8
  • 61
  • 146