Q:

Question about trailing return type in C++17

I have the following piece of code which compiles fine:
template <typename T> 
struct A {T t;};

template <typename T> // 1 
A(T) -> A<T>;  // function template declaration with trailing return type compiles fine.

But the following variations of the same function declaration do not compile:
template <typename T>  // 2
auto A(T) -> A<T>; // error: redefinition of 'A' as different kind of symbol

template <typename T>  // 3
A<T> A(T); // error: redefinition of 'A' as different kind of symbol

please help me in understanding the rationale behind why those didn't compile

A:

// function template declaration with trailing return type compiles fine.

template <typename T> // 1 
A(T) -> A<T>;  // function template declaration with trailing return type compiles fine.

Not exactly.
For a function declaration with explicit trailing return type, you have to add auto before the name of the function.
Your "1" code example it's a new C++17 user defined deduction guide (see this page for more information).
Given your template A class, you're saying the compiler that when you define a variable as follows
A  a{42l};

you're defining a A<long> variable, because the type of the template parameter is deduced from the argument of the constructor (42l).
About following codes
template <typename T>  // 2
auto A(T) -> A(T); // error: use of class template 'A' requires template  arguments

Now you're using correctly auto before the name, so you're declaring a function; unfortunately the name can't be A (it's the name of a struct) and the return type can't be A(T) (maybe A<T>)
template <typename T>  // 3
A<T> A(T); // error: redefinition of 'A' as different kind of symbol

Now you're correctly declaring a template function returning an A<T> but remain the other problem: the name can't be A (it's the name of a struct)

