In the following code there is an initialization of A<T>
objects with template argument deduction using two forms distinct by the type of braces:
template<typename T>
struct A{ T x; };
int main() {
static_assert( A{1}.x == 1 ); //#1: ok in GCC and MSVC
static_assert( A(1).x == 1 ); //#2: ok in GCC only
}
The first way is accepted by both GCC and MSVC, while the second one is ok for GCC only while MSVC prints errors:
error C2641: cannot deduce template arguments for 'A'
error C2780: 'A<T> A(void)': expects 0 arguments - 1 provided
error C2784: 'A<T> A(A<T>)': could not deduce template argument for 'A<T>' from 'int'
Demo: https://gcc.godbolt.org/z/97G1acqPr
Is it a bug in MSVC?
If you compile this in C++17, you’ll likely get some error about “CTAD argument deduction failed” or “cannot deduce template arguments” or “No viable constructor or deduction guide”. This is because in C++17, CTAD doesn’t know how to deduce the template arguments for aggregate class templates.
Template argument deduction is used in declarations of functions, when deducing the meaning of the auto specifier in the function's return type, from the return statement.
Type template parameter cannot be deduced from the type of a function default argument: Deduction of template template parameter can use the type used in the template specialization used in the function call: Besides function calls and operator expressions, template argument deduction is used in the following situations:
Before class template argument deduction was introduced, a common approach to avoiding explicitly specifying arguments is to use a function template: The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
This is a bug in MSVC.
The following papers were all introduced in C++20:
Whilst MSVC lists them all as implemented in their Microsoft C/C++ language conformance by Visual Studio version pages, it seems whilst they have correctly implemented them in isolation
// OK (P0960R3, P1975R0)
struct A { int x; };
A a(1);
// OK (P2131R0)
template<typename T>
struct B { T x; };
B b{1};
// rejects-invalid (allowed by the union of the papers)
template<typename T>
struct C { T x; };
C c(1);
MSVC seems to have missed implementing the union of the papers. I have not, however, been able to find an open bug report.
These lines being well-formed relies on an aggregate deduction candidate, which provides a way for T
to be deduced from aggregate intialization lists. This feature is indifferent to the syntax, so failing on either one but not the other is already inconsistent.
In MSVC's case, it's the combination of class template parameter deduction and parenthesized aggregate intialization that is causing the issue (the latter works fine in isolation). MSVC also fails to compile A a(1);
, which is more obviously well-formed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With