非成员模板友元函数默认参数值错误
Error for default parameter value of non-member template friend function
为什么下面的代码可以用 GCC 编译但不能用 Clang 编译?谁是对的,为什么?
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)
{
}
我在使用 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 版本:g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
clang版本:clang版本6.0.0-1ubuntu2
我该如何解决这个问题?
这是gcc的bug which has been fixed; clang is correct. When specifying default argument友元声明,
If a friend declaration specifies a default, it must be a friend function definition, and no other declarations of this function are allowed in the translation unit.
也就是说你在声明函数的同时要定义函数friend
。
根据标准,[dcl.fct.default]/4
If a friend declaration specifies a default argument expression, that declaration shall be a definition and shall be the only declaration of the function or function template in the translation unit.
顺便说一句:Gcc 11 也不编译。
How do I resolve this?
如错误消息所述,您必须定义函数模板才能拥有默认参数:
template <typename T>
friend void F(T x, S s, int v = 5) {
// ...
}
如果您不想这样,您可以删除默认参数并添加一个作为代理的重载:
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); }
另一种选择是对函数进行前向声明:
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>);
// ...
}
为什么下面的代码可以用 GCC 编译但不能用 Clang 编译?谁是对的,为什么?
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)
{
}
我在使用 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 版本:g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
clang版本:clang版本6.0.0-1ubuntu2
我该如何解决这个问题?
这是gcc的bug which has been fixed; clang is correct. When specifying default argument友元声明,
If a friend declaration specifies a default, it must be a friend function definition, and no other declarations of this function are allowed in the translation unit.
也就是说你在声明函数的同时要定义函数friend
。
根据标准,[dcl.fct.default]/4
If a friend declaration specifies a default argument expression, that declaration shall be a definition and shall be the only declaration of the function or function template in the translation unit.
顺便说一句:Gcc 11 也不编译。
How do I resolve this?
如错误消息所述,您必须定义函数模板才能拥有默认参数:
template <typename T>
friend void F(T x, S s, int v = 5) {
// ...
}
如果您不想这样,您可以删除默认参数并添加一个作为代理的重载:
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); }
另一种选择是对函数进行前向声明:
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>);
// ...
}