I hope this is a good audience.
Title seems long an convoluted, but the problem boiled down to gcc and
clang disagreeing on such code:
(This is a grokked version of code which we got during a real world
code-base evolution [if that means anything])
#include <type_traits>
#include <iostream>
#include <string>
template <typename T>
struct B {
template <typename U>
using nested_templated_using = U;
template<typename U = T, nested_templated_using<U>* = nullptr >
void f();
};
template <typename T>
template <typename U, typename B<T>::template nested_templated_using<U>* >
// ^ should typename be here or not?
void B<T>::f(){ }
int main () { return 0;}
[godbolt example](Compiler Explorer)
clang requires `typename` keyword in the indicated spot, while gcc
forbids it. They error out with the same message indicating that the
out-of-line definition does not match declaration.
I've asked this question on
[stackoverflow](c++ - gcc doesn't accept out-of-line definition of member with non-type template parameter defined via nested templated using clause - Stack Overflow) but it
wasn't clear yet what is the core issue, I thought gcc misbehaves.
I got some great input by Johannes Schaub, who pointed [CWG issue
#2](C++ Standard Core Language Active Issues) and
[CWG issue #560](C++ Standard Core Language Active Issues).
They both treat about referring to the dependent types, though as the
type of return value.
My thoughts are:
1. The type of the parameter is dependent.
2. I am not sure whether the type of the parameter is "a member of the
current instantiation" as understood in
[temp.res#3]([temp.res])
3. In conjunction with [temp.res#5]([temp.res])
above renders "wrong guess" about the presence of the keyword a killer
- program is ill-formed.
I might be wrong in my toughts, and I am not sure whether, or not,
`typename` keyword usage changes for non-type template parameters.
Also, inline definition does not require the keyword.
It would be nice if someone could give authoritative answer
(preferably stepping through standard) whether:
1. clang is wrong.
2. gcc is wrong.
3. standard is unclear.
Regards,
Łukasz.