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.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Newline
  • 769
  • 3
  • 12

1 Answers1

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.

lisyarus
  • 15,025
  • 3
  • 43
  • 68
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • I see. it works with GCC on godbolt, it doesn't work with Clang which is what I'm using. – Newline Jan 19 '22 at 07:31
  • @Newline Yes, [Clang](https://clang.llvm.org/cxx_status.html#cxx20) hasn't supported that. You cand add a user-defined deduction guide. – songyuanyao Jan 19 '22 at 07:35
  • I've tweaked the final remark slightly - the feature was [commited](https://reviews.llvm.org/D139837) in December 2022, and will probably be in Clang 17. – lisyarus Aug 07 '23 at 15:32