Closed ranaanoop closed 6 months ago
The divergence is probably from a bug of MSVC. Actually, all 3 compilers currently treat force2
as a variable template (Godbolt link).
#include <typeinfo>
#include <cstdio>
template <typename T>
void func(T); // a function template
template <typename T>
using WithDecltype = decltype(func<T>); // alias for function type
template <typename T>
WithDecltype<T> force2; // All 3 compilers think this is an invalid variable template.
template <typename T>
using WithExplicitDeclarator = void(T); // alias for function type
template <typename T>
WithExplicitDeclarator<T> force3; // valid function template
template<auto V>
struct type_tag {};
int main()
{
std::puts(typeid(type_tag<force2<char>>).name()); // rejected
std::puts(typeid(type_tag<force3<char>>).name()); // accepted
}
I failed to find why force2
is problematic. Perhaps [temp.type] p4 is related.
all 3 compilers currently treat force2 as a variable template
@frederick-vs-ja No, they don't. See the error messages(from gcc and clang) in this demo which explicitly say that error: variable 'force2' has function type
. I did checked this before posting the original issue also. Did I miss something?
For reference, here is the code that shows that gcc and clang considers force2
to be a function type while msvc considers it a variable template.
template <typename N>
void func(N a);
template <typename N>
using ForceType = decltype(func<N>);
template <typename N>
ForceType<N> force2;
constexpr int i = force2<int>; //gcc and clang says force2 has function type but msvc says a specialization of variable template cannot have type void (N)
GCC says:
<source>:9:14: error: variable 'force2' has function type
9 | ForceType<N> force2;
| ^~~~~~
While msvc says:
<source>(11): error C7532: 'force2': a specialization of variable template cannot have type 'void (N)'
with
[
N=int
]
<source>(11): error C2440: 'initializing': cannot convert from 'void (N)' to 'const int'
with
While clang says:
error: variable instantiated with function type 'ForceType<int>' (aka 'void (int)')
9 | ForceType<N> force2;
| ^
<source>:11:19: note: in instantiation of variable template specialization 'force2' requested here
11 | constexpr int i = force2<int>;
For reference, here is the code that shows that gcc and clang considers
force2
to be a function type while msvc considers it a variable template.
No, they consider the type of force2
to be a function type. Per these error messages, gcc and clang also consider the specialization of force2
a variable. They are just omitting the "template" part in the diagnostics.
IIRC all 3 compilers agree on that
force2<int>
is a variable (and thus a specialization of a variable template, but why?)ForceType<int>
, that is void(int)
) being a function type (obviously correct to me).CWG2862 may be related - the proposed resolution attempts to make distinction between function templates and variable templates.
- A function template is introduced by a template-declaration whose declaration declares a function.
- [...]
- A variable template is introduced by a template-declaration whose declaration declares a variable.
However, the type in the declaration may be a dependent type that is "not obviously a function type or not", and may be conditionally a function type or an object type.
Perhaps we should address such edge cases. @jensmaurer
A dependent type can't turn a (syntactic) variable declaration into a function declaration at instantiation time: temp.spec.general p8.
So is it intended not to disambiguate function and variable templates in the proposed resolution of CWG2862 because ambiguous cases are ill-formed?
Yes. If the declaration syntactically declares a variable, it can't declare a function (template) later.
Full name of submitter: Anoop Rana
Reference (section label):
Issue description:
The following program shows implementation divergence.
It is not clear if
force2
is supposed to be a variable template or a function declaration.