我有一个非常简单的问题:某个地方有一个函数
int size (const C & c)
它至少是通过依赖于参数的名称查找找到的。现在的问题是:
struct B
{
int size () { /* ... */ }
void doSomething (const C & c)
{
int x = size (c); // <----------- problem!
// ...
}
}
这不起作用,因为在找到成员函数之后,名称查找就停止了。
如果不尝试调用成员函数,而是编译器执行如果成员函数不存在的话,那么我必须在指定的行中写入什么呢?
请注意,该解决方案并不是编写::size
,因为这样可以防止参数依赖的名称查找,并且只有当我知道size
在哪里声明时才能工作。
进一步并发症:
我知道,对于我使用以下模板成员函数B::doSomething
的每个相关类型的B::doSomething
,都会有一个函数
int size (const T & t)
它至少是通过依赖于参数的名称查找找到的。B
看起来如下:
struct B
{
int size () { /* ... */ }
template<class T>
void doSomething (const T & t)
{
int x = size (t); // <----------- problem!
// ...
}
}
我希望调用非会员函数(我确信它存在,但我不能确定它在哪里)。
发布于 2015-08-19 09:15:25
这是一个众所周知的问题,它的解决办法也是众所周知的.我很惊讶这件事还没被提起。如果您有一个非成员函数,如下所示:
class C;
size_t size( C const &c );
您可以使用using
声明比成员函数更好地查找名称:
struct B {
size_t size();
void foo( C const &c ) {
using ::size;
size_t sz = size(c);
}
};
当编译器看到对size(c)
的调用时,它从最内部的作用域开始,并向外搜索名为size
的内容。如果没有using
声明,编译器就会在全局命名空间中的非成员之前在类范围内找到成员函数,但是using
声明会改变这一点。最内部的作用域是函数本身,使用声明在成员函数之前找到。
这样做的好处是,您仍然可以获得依赖于参数的查找(ADL),因为对size(c)
的实际调用是不合格的。这意味着您可以在模板中使用它:
template <class T>
void foo( T const &c ) {
using ::size;
size_t sz = size(c);
}
..。即使正确的size
函数位于另一个名称空间中,它也会被ADL找到。using
声明只需要引用一些size
函数,而不一定是您真正想要的函数。正常情况下,在某个地方有一个可能调用该成员的默认实现。下一个版本的C++标准(C++17)几乎肯定会有一个std::size
函数来实现这一点。一旦它被广泛使用,你就可以写
using std::size;
size_t sz = size(c);
目前,您可以提供自己的默认实现,如下所示:
template <class C>
constexpr auto size( C const &c ) -> decltype(c.size()) {
return c.size();
}
..。或者您可以继续引用C
的版本,并依赖于ADL找到正确的版本。
发布于 2012-11-15 22:19:07
如果不能重命名自己的成员函数,则可以使用一个肮脏的技巧:
static inline int dirty_trick(C const & c)
{
return size(c);
}
void B::doSomething(C const & c)
{
int x = dirty_trick(c);
// ...
}
发布于 2015-08-20 19:50:57
为了完整,并在Richard Smith所接受的答案中添加了以下内容:
我现在的解决方案如下:
namespace adl {
// This declaration's only purpose is the possibility to refer to
// a non-member function named "size" in a using declaration.
//
// The signature does not matter, so we choose the easiest possible one.
void size ();
}
struct B
{
int size () { /* ... */ }
template<class T>
void doSomething (const T & t)
{
using adl::size;
int x = size (t); // <----------- no problem anymore
// ...
}
};
这样,我就不必包含任何可能实际上不需要的标题。
https://stackoverflow.com/questions/13407205
复制相似问题