Search code examples
c++templatesinitializationc++20ctad

C++ - Why does aggregate initialization not work with template struct


This code works, without having to specify a constructor:

struct Foo
{
    int a;
    int b;
};

//...

    int a1, b1;

    Foo foo = {a1, b1};

If I make Foo a template, it doesn't work.

template<typename T1, typename T2>
struct Foo
{
    T1 a;
    T2 b;
};

//...

    int a1, b1;

    Foo foo = {a1, b1};

It says deduction failed / 2 arguments were provided while 1 expected. If I add a constructor like Foo(T1, T2){} then it works. I thought, that sort of construction just works by default for structs. What am I getting wrong?

EDIT: I'm using Clang, which seems not to support it. Both MSVC and GCC compile it with c++20 compiler flag.


Solution

  • Since C++20 aggregates have implicitly-generated deduction guide so class template argument deduction works for aggregates too.

    int a1, b1;
    Foo foo = {a1, b1}; // works since C++20; T1 and T2 are deduced as int
    

    Before C++20, you need to add user-defined deduction guide, e.g.

    template<typename T1, typename T2>
    struct Foo
    {
        T1 a;
        T2 b;
    };
    
    template<class T1, class T2> Foo(T1 a, T2 b) -> Foo<T1, T2>;
    

    As of Aug 2023, Clang has not supported class template argument deduction for aggregates yet, but the most recent Clang trunk does support it and, apparently, this will be supported in Clang 17.