我有一个非常简单的问题:某个地方有一个功能
int size (const C & c)
Run Code Online (Sandbox Code Playgroud)
至少可以通过参数依赖的名称查找找到它.现在的问题是:
struct B
{
int size () { /* ... */ }
void doSomething (const C & c)
{
int x = size (c); // <----------- problem!
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为名称查找在找到成员函数后停止.
我必须在指示的行中写什么,以便不会尝试调用成员函数,但是,如果成员函数不存在,编译器会做什么呢?
请注意,解决方案不是写入::size,因为这会阻止依赖于参数的名称查找,并且只有在我知道size声明的位置时才有效.
进一步复杂化:
我知道对于T我使用下面模板化成员函数的每个相关类型B::doSomething,某处会有一个函数
int size (const T & t)
Run Code Online (Sandbox Code Playgroud)
至少可以通过参数依赖的名称查找找到它.B看起来如下:
struct B
{
int size () { /* ... */ }
template<class T>
void doSomething (const T & t)
{
int x = size (t); // <----------- problem!
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
我希望调用非成员函数(我确信它存在,但我无法确定它在哪里).
Ric*_*ith 10
这是一个众所周知的问题,其解决方案同样众所周知.我很惊讶它尚未被提及.如果您有非成员函数,例如:
class C;
size_t size( C const &c );
Run Code Online (Sandbox Code Playgroud)
您可以使名称查找优先于具有using声明的成员函数找到它:
struct B {
size_t size();
void foo( C const &c ) {
using ::size;
size_t sz = size(c);
}
};
Run Code Online (Sandbox Code Playgroud)
当编译器看到调用时size(c),它从最里面的范围开始并向外搜索命名的内容size.如果没有using声明,编译器就会在全局命名空间中的非成员之前找到类范围中的成员函数,但using声明会更改它.最里面的范围是函数本身,并且在成员函数之前找到using声明.
这样做的好处在于您仍然可以获得与参数相关的查找(ADL),因为实际调用size(c)是不合格的.这意味着您可以在模板中使用它:
template <class T>
void foo( T const &c ) {
using ::size;
size_t sz = size(c);
}
Run Code Online (Sandbox Code Playgroud)
...即使正确的size函数在另一个命名空间中,ADL也会找到它.该using声明只是需要引用一些 size功能,并不一定是你真正想要的.在一个可能调用成员的地方有一个默认实现是很正常的.下一版本的C++标准(C++ 17)几乎肯定会有一个std::size完全正确的功能.一旦广泛使用,您就可以写作了
using std::size;
size_t sz = size(c);
Run Code Online (Sandbox Code Playgroud)
目前,您可以提供自己的默认实现,例如:
template <class C>
constexpr auto size( C const &c ) -> decltype(c.size()) {
return c.size();
}
Run Code Online (Sandbox Code Playgroud)
...或者您可以继续参考该版本C,并依赖ADL找到合适的版本.
如果你不能重命名你自己的成员函数,你可以使用一个肮脏的技巧:
static inline int dirty_trick(C const & c)
{
return size(c);
}
void B::doSomething(C const & c)
{
int x = dirty_trick(c);
// ...
}
Run Code Online (Sandbox Code Playgroud)