GCC下模板类友元函数声明引发非模板函数警告的解决方法
GCC下模板类友元函数模板的警告与遮蔽问题解决办法
问题场景
这段C++代码可在Clang、MSVC正常编译,但GCC会抛出「友元声明的是非模板函数」的警告;若直接在类内友元声明前添加template <typename T>,又会触发「模板参数T被遮蔽」的编译错误。
原代码示例
#include <memory> #include <cstdio> /* header.hpp */ template <typename T> class entity; template <typename T> auto create_entity() -> std::shared_ptr<entity<T>>; template <typename T> class entity { // template <typename T> friend auto create_entity() -> std::shared_ptr<entity<T>>; }; /* impl.cpp */ template <typename T> auto create_entity() -> std::shared_ptr<entity<T>> { return std::make_shared<entity<T>>(); } int main() { create_entity<int>(); }
GCC警告信息(中文翻译)
<source>:16:41: 警告:友元声明'std::shared_ptr<entity<T> > create_entity()'声明了一个非模板函数 [-Wnon-template-friend] 16 | friend auto create_entity() -> std::shared_ptr<entity<T>>; | ^~~~~~~~~~~~~~~~~~~~~ <source>:16:41: 提示:(若这并非你的意图,请确保函数模板已提前声明,并在此处函数名后添加'<>')
解决办法
方法一:明确引用已声明的模板函数实例
在友元声明的函数名后添加<T>,明确指定该友元是对应类模板参数T的create_entity模板实例,而非新的非模板函数:
template <typename T> class entity { friend auto create_entity<T>() -> std::shared_ptr<entity<T>>; };
此方式精准关联了与当前类实例匹配的模板函数,消除警告的同时避免参数遮蔽问题。
方法二:使用不重复的模板参数名声明友元模板
若希望将所有create_entity的模板实例都声明为友元,可改用不同的模板参数名(如U),避免与类模板的T冲突:
template <typename T> class entity { template <typename U> friend auto create_entity() -> std::shared_ptr<entity<U>>; };
此方式会让任意create_entity<U>都拥有entity<T>的访问权限,适用于需要更宽泛友元权限的场景。
内容的提问来源于stack exchange,提问作者glades
相关产品推荐
相关产品推荐

