C++ 将constexpr专门化声明为友元

C++ 将constexpr专门化声明为友元,c++,c++11,gcc,clang,constexpr,C++,C++11,Gcc,Clang,Constexpr,我有一个模板类a和一个模板函数f,它返回a对象。我希望f成为a的朋友,并且仍然是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

我有一个模板类
a
和一个模板函数
f
,它返回
a
对象。我希望
f
成为
a
的朋友,并且仍然是
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>();
}
如果我在friend声明中将它标记为
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>();
main.cpp:9:27:错误:友元模板专用化“af()的声明中不允许使用“constexpr”
friend constexpr A f();
我怎样才能让每个人都快乐

int main(){constexpr auto a=f();}
int main() { constexpr auto a  = f<void>(); }
这将函数模板
f
专门化为函数
f()
;在
f
的专门化过程中,编译器还尝试实例化
A
,这反过来又声明了专门化
friend f()

这两个声明必须与
constexpr
匹配:

[dcl.constexpr]/1

[…]如果函数或函数模板的任何声明具有
constepr
说明符,则其所有声明都应包含
constepr
说明符。[注:显式专门化可能与模板声明中的
constepr
说明符不同。-结束注]

当您在
friend
声明中省略
constexpr
而不是删除看似非
constexpr
函数时,Clang可能会在前面出错,但至少它接受正确的语法

Gcc不允许缺少
constepr
的版本,并且在您提供
constepr
时,由于错误而给出错误。这已经在主干中修复,我可以确认它现在可以工作了,尽管当
constexpr
丢失时,它仍然没有提供错误。

有关类似的错误,请参阅
int main() { constexpr auto a  = f<void>(); }