c++templatesmost-vexing-parse

Why can't I create a temporary of this templated class with an lvalue constructor argument?


For the life of me I can't seem to create a temporary of this class, why isn't it allowing me to?

template <typename T>
struct Dog
{
    Dog(T t) : tag(t) {}
    T tag; 
};

int main()
{
    int tag = 6;
    Dog<int>(6); // Works fine
    Dog<int>(tag); // On Visual Studio I get no default constructor exists for class Dog<int>
                  // On onlineGDB I get error: no matching function for call to ‘Dog::Dog()’
}

Also, what's the difference here, again between rvalue and lvalue:

Dog(6); // Deduces fine
Dog(tag); // Deduction fail, error: missing template arguments before ‘(’ token

Also:

Dog<int>{tag}; // Works. 

I take it because this is aggregate initialization?


Solution

  • Dog(6); and Dog<int>(6); declare temporary Dog<int>s, constructed with the value 6. Template argument deduction works fine in the first case, and the template parameter is explicit in the second.

    However, Dog(tag); is not creating a temporary. It's a declarator of a variable tag of type Dog<?>. In general, the parentheses are redundant, i.e. int x, int (x), int ((x)) are all equivalent. In this case, the error is that you haven't given an initializer with which to deduce the template parameter of Dog. The other error is you can't have parentheses around declarators where you're doing class template argument deduction.

    Dog<int>(tag); is similar, it's a declarator of a variable tag of type Dog<int>. No deduction needs to be done since the parameter is explicit, but the error here is that you don't have a default constructor for Dog, and you haven't provided an argument for the constructor yourself.

    Dog{tag}; doesn't have the same issue as with parentheses. It declares a temporary Dog constructed with tag as you expected.