Why does the following code compile with GCC but not with Clang? Who is right and why?
class TF
{
private:
struct S
{
};
template <typename T> friend void F(T x, S s, int v = 5);
};
template <typename T>
void F(T x, TF::S s, int v)
{
}
I get following error with clang++:
error: friend declaration specifying a default argument must be a definition
template <typename T> friend void F(T x, S s, int v = 5);
^
error: friend declaration specifying a default argument must be the only declaration
void F(T x, TF::S s, int v)
^
note: previous declaration is here
template <typename T> friend void F(T x, S s, int v = 5);
GCC version: g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Clang version: clang version 6.0.0-1ubuntu2
How do I resolve this?
How do I resolve this?
As the error message says, you must define the function template to be able to have default arguments:
template <typename T>
friend void F(T x, S s, int v = 5) {
// ...
}
If you don't want that, you could remove the default argument and add an overload that acts as a proxy:
template <typename T>
friend void F(T x, S s, int v);
// ...
template <typename T>
void F(T x, TF::S s, int v) {
// ...
}
template <typename T>
void F(T x, TF::S s) { F(x, s, 5); }
Another option is to make a forward declaration of the function:
template <typename T, typename S>
void F(T x, S s, int v = 5);
class TF {
private:
struct S {};
template <typename T, typename S>
friend void F(T x, S s, int v);
};
template <typename T, typename S>
void F(T x, S s, int v) {
static_assert(std::is_same_v<S, TF::S>);
// ...
}