将 constexpr 特化声明为友元
Declaring a constexpr specialization as friend
我有一个模板化的 class A
和一个模板化的函数 f
returns A
对象。我希望 f<T>
成为 A<T>
的朋友并且仍然是 constexpr
template <typename T>
class A;
template <typename T>
constexpr A<T> f();
//f<T> is a friend of A<T>
template <typename T>
class A {
friend /* constexpr? */ A f<T>();
constexpr A() {}
};
template <typename T>
constexpr A<T> f() { return {}; }
int main() {
constexpr auto a = f<void>();
}
我无法让 clang 和 gcc 就此处的内容达成一致。如果我不把 constexpr
放在朋友声明中,gcc 工作正常但 clang 不会编译它,错误为:
main.cpp:18:18: error: constexpr variable 'a' must be initialized by a constant expression
constexpr auto a = f<void>();
^ ~~~~~~~~~
main.cpp:18:23: note: non-constexpr function 'f<void>' cannot be used in a constant expression
constexpr auto a = f<void>();
^
main.cpp:9:12: note: declared here
friend A f<T>();
如果我在友元声明中将其标记为 constexpr
,clang 编译正常,但 gcc 给我错误:
main.cpp:9:27: error: 'constexpr' is not allowed in declaration of friend template specialization 'A<T> f<T>()'
friend constexpr A f<T>();
我怎样才能让每个人都开心?
int main() { constexpr auto a = f<void>(); }
这将函数模板 f
特化为函数 f<void>()
;在 f
的特化期间,编译器还尝试实例化 A<void>
,后者又声明特化 friend f<void>()
.
这两个声明必须匹配constexpr
:
[dcl.constexpr] / 1
[...] If any declaration of a function or function template has a constexpr
specifier, then all its declarations shall contain the constexpr
specifier. [Note: An explicit specialization can differ from the template declaration with respect to the constexpr
specifier. —end note]
当您在 friend
声明中省略 constexpr
时,Clang 可能会更早地出错,而不是消除看似非 constexpr
函数的内容,但至少它接受正确的语法。
Gcc 不应允许缺少 constexpr
的版本,并且当您提供 constexpr
时由于 bug 会给出错误。这已经在主干中得到修复,我可以确认它现在可以工作,尽管当缺少 constexpr
时它仍然没有提供错误。
我有一个模板化的 class A
和一个模板化的函数 f
returns A
对象。我希望 f<T>
成为 A<T>
的朋友并且仍然是 constexpr
template <typename T>
class A;
template <typename T>
constexpr A<T> f();
//f<T> is a friend of A<T>
template <typename T>
class A {
friend /* constexpr? */ A f<T>();
constexpr A() {}
};
template <typename T>
constexpr A<T> f() { return {}; }
int main() {
constexpr auto a = f<void>();
}
我无法让 clang 和 gcc 就此处的内容达成一致。如果我不把 constexpr
放在朋友声明中,gcc 工作正常但 clang 不会编译它,错误为:
main.cpp:18:18: error: constexpr variable 'a' must be initialized by a constant expression
constexpr auto a = f<void>();
^ ~~~~~~~~~
main.cpp:18:23: note: non-constexpr function 'f<void>' cannot be used in a constant expression
constexpr auto a = f<void>();
^
main.cpp:9:12: note: declared here
friend A f<T>();
如果我在友元声明中将其标记为 constexpr
,clang 编译正常,但 gcc 给我错误:
main.cpp:9:27: error: 'constexpr' is not allowed in declaration of friend template specialization 'A<T> f<T>()'
friend constexpr A f<T>();
我怎样才能让每个人都开心?
int main() { constexpr auto a = f<void>(); }
这将函数模板 f
特化为函数 f<void>()
;在 f
的特化期间,编译器还尝试实例化 A<void>
,后者又声明特化 friend f<void>()
.
这两个声明必须匹配constexpr
:
[dcl.constexpr] / 1
[...] If any declaration of a function or function template has a
constexpr
specifier, then all its declarations shall contain theconstexpr
specifier. [Note: An explicit specialization can differ from the template declaration with respect to theconstexpr
specifier. —end note]
当您在 friend
声明中省略 constexpr
时,Clang 可能会更早地出错,而不是消除看似非 constexpr
函数的内容,但至少它接受正确的语法。
Gcc 不应允许缺少 constexpr
的版本,并且当您提供 constexpr
时由于 bug 会给出错误。这已经在主干中得到修复,我可以确认它现在可以工作,尽管当缺少 constexpr
时它仍然没有提供错误。