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

1

7

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.

Boric answered 19/1, 2022 at 7:16 Comment(4)
It works when you explicitly specify Foo<Int, int> foo = {a1, b1};. godbolt.org/z/Eqcc7PefnHomopterous
Does this answer your question? initializer_list and template type deductionBetook
This should make compilation possible Foo foo = {{a1, b1}};.Meprobamate
Your compiler probably doesn't implement the whole of C++20. An aggregate deduction guide should be synthesised.Sterne
M
10

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.

Moline answered 19/1, 2022 at 7:27 Comment(3)
I see. it works with GCC on godbolt, it doesn't work with Clang which is what I'm using.Boric
@Boric Yes, Clang hasn't supported that. You cand add a user-defined deduction guide.Moline
I've tweaked the final remark slightly - the feature was commited in December 2022, and will probably be in Clang 17.Rhizoid

© 2022 - 2024 — McMap. All rights reserved.