CppCoreGuidelines T.69 在模板里,不要调用无限定的非成员函数,除非你有意以其作为定制点
27 September 2023
“Inside a template, don’t make an unqualified non-member function call unless you intend it to be a customization point”
理由
- 只提供必要的灵活性
- 避免环境改变导致的漏洞
例子
主要有三种方式,让调用的代码定义一个模板
template<class T> // Call a member function void test1(T t) { t.f(); // require T to provide f() } template<class T> void test2(T t) // Call a non-member function without qualification { f(t); // require f(/*T*/) be available in caller's scope or in T's namespace } template<class T> void test3(T t) // Invoke a "trait" { test_traits<T>::f(t); // require customizing test_traits<> // to get non-default functions/types }
trait
一般就是一个计算类型的类型别名,一个计算值的 constexpr
函数,或者一个传统的 traits 模板,用于根据用户提供的类型实例化模板。
注意
如果你计划调用你自己定义的帮助函数 helper(t)
,而且这个 t
有依赖于模板类型参数。那么可以把 helper
放在 ::detail
名字空间,然后通过限定的
detail::helper(t)
调用。而一个未限定的调用则会成为一个定制化点,任何 t
类型名字空间里的 helper
函数都可以调用。这可能会造成问题,比如你不小心调用了未限定的函数模板。
强化
在模板中,标记调用未限定的非成员函数,且传入一个依赖于模板类型的变量,并且,在模板名字空间内还有一个一样名字的非成员函数。