I am using a decltype to ensure a template function force2 has the same parameter and return types as another template function force1 but it doesn't compile. I require the functions to be templated.
Consider this code:
template <typename N>
void force1(N a);
template <typename N>
using ForceType = decltype(force1<N>);
template <typename N>
ForceType<N> force2;
template <typename N>
void force2(N a)
{}
This results in an error:
<source>:11:16: error: 'template<class N> void force2(N)' conflicts with a previous declaration
11 | void force2(N a)
| ^
<source>:8:14: note: previous declaration 'template<class N> ForceType<N> force2<N>'
8 | ForceType<N> force2;
| ^~~~~~
Compiler returned: 1
I expected this to compile: with force2 being a templated function with empty body. What is actually going on over here? The compiler hints that template<class N> void force2(N) is not the same as template<class N> ForceType<N> force2<N> which I am not able to understand. They definitely seem different on the first look but shouldn't the expansion of ForceType<N> result in template<class N> void force2(N)?
When I use a concrete type in declaration of force2:
template <typename N>
void force1(N a);
template <typename N>
using ForceType = decltype(force1<N>);
ForceType<int> force2;
void force2(int a)
{}
It compiles without errors.
ForceType<N>is a dependent type.[temp.spec.general]p8:
ForceType<N> force2;does not meet this requirement, so this is ill-formed.In compilers, this will be parsed as a variable template since, because of the above rule, it cannot be a function template.
Any attempt to actually use
force2<N>will result in an error (https://godbolt.org/z/f3Ke3x8db)And even if you were to fix it by making it of the form of a function declaration:
This would declare two separate templates overloads because
ForceType<N>andvoid(N)are not equivalent (i.e., the latter is not a definition of the former)