如何从客户端代码中隐藏模板化的非成员函数?
How to hide a templated non-member function from client's code?
我有模板函数,比如
template<class T>
void mysort(std::vector<T>& vec)
{
size_t b, m, e,
...
mysort(vec, b, m, e);
}
template<class T>
void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)
{
size_t x, y, z;
...
mysort (vec, x, y, z);
}
公共接口是只接受vector引用的接口。我想隐藏另一个,实现,所以没有客户端代码可以做
mysort(vec, a, b, c);
创建一个类并使实现函数私有静态感觉不对,我尝试使用匿名命名空间,
namespace abc
{
namespace
{
template<class T>
void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
}
template<class T>
void mysort(std::vector<T>& vec)...
}
它有帮助,但不是完全击倒…
#include "mysort.h"
int main()
{
...
abc::mysort(vec, a, b, c); // this won't compile, good
}
但是如果我把它改成:
#include "mysort.h"
using namespace abc;
int main()
{
...
mysort(vec, a, b, c); // it compiles and runs!!
}
我在x86_64上使用gcc Ubuntu 4.4.3-4ubuntu5。有人能解释为什么它用指令编译,而不是用限定的名字,以及是否有更好的方法来实现我想要的?
通常的做法是创建一个"detail"名称空间,该名称空间仅用于内部使用的代码:
namespace abc
{
namespace detail
{
template<class T>
void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
}
template<class T>
void mysort(std::vector<T>& vec)...
}
回答您关于未命名命名空间行为的问题:
未命名的名称空间(它们不称为匿名名称空间)的命名有点奇怪——它们对您来说是未命名的,但编译器实际上为它生成一个唯一的内部名称。你的例子相当于:
namespace abc
{
namespace def // lets say 'def' is unique.
{
template<class T>
void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
}
using namespace def;
template<class T>
void mysort(std::vector<T>& vec)...
}
你会注意到它的行为和你未命名的例子一样:你不能在这里做abc::mysort(vec, 1, 2, 3)
,但你可以做using namespace abc; mysort(vec, 1, 2, 3)
。
这是因为没有两个abc::mysort
s,只有一个abc::def::mysort
和abc::mysort
。当你声明一个实际的abc::mysort
时,它隐藏了using namespace def
带来的那个。注意,如果注释掉只有1个参数的mysort
,实际上可以写成abc::mysort(vec, 1, 2, 3)
。
因为它是隐藏的,所以对abc::mysort
的合格调用必须显式地查看abc::mysort
,并且只能找到1参数版本。
然而,对于通过using namespace abc; mysort(vec, 1, 2, 3)
的非限定调用,它可以使用ADL找到任何匹配的可用函数
我做了更多的测试,实际上,在更高的版本gcc (Ubuntu/Linaro 4.6.3-1ubuntu5)和-std=c++0x中,它完全符合我的期望。
在主文件中,using指令或使用限定名都不允许你在一个匿名命名空间中调用函数,而这个匿名命名空间本身又在另一个命名空间中。
我认为原因是编译器确认了最新的标准,该标准规定未命名的命名空间默认具有内部链接。
在我看来,未命名的名称空间方法应该优于旧的"细节"名称空间实践。
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 将公共但非静态的成员函数与ALGLIB集成
- 使用指向成员的指针将成员函数作为参数传递
- 将重载的成员函数传递给函数模板
- 我不小心调用了一个没有自己类对象的成员函数.但这是怎么回事呢
- 如何在C++中使用非静态成员函数作为回调函数
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 关联容器的下界复杂性:成员函数与非成员函数
- 在 C++ 中用派生类型重写成员函数
- 链表的泛型函数remove()与成员函数remove)
- 如何将lambda作为模板类的成员函数参数
- constexpr构造函数需要常量成员函数时出现问题
- 将自由函数绑定为类成员函数
- 区分非成员函数和头文件中的成员函数
- 如何从子成员函数修改父公共成员变量
- 保留对其他类的成员函数的引用
- 在运算符重载定义中使用成员函数(const错误)
- 内联如何影响模块接口中的成员函数
- 将成员函数指针作为参数传递给模板方法