使用简单的qtest将用户定义的结构比较2个不同的对象时:
Test a, b = {1};
QCOMPARE(a, b);
为什么两者之间有区别?
(1)
static char* toString(const Test &)
{
using QTest::toString;
return toString("Test");
}
还有
(2)
namespace {
char* toString(const Test &)
{
using QTest::toString;
return toString("Test");
}
} // unnamed namespace
第一个在比较对象时会调用该函数,第二个则不会!
如in this conclusion所述,除了匿名名称空间允许您定义本地翻译单元类型之外,应该没有其他区别。好吧,这看起来恰恰相反。
答案 0 :(得分:2)
默认的QTest::toString
实现是一个功能模板:
template <class T> char *QTest::toString(const T &value);
专业化此模板似乎是提供自定义实现的一种方法,但是您正在使用另一种方法,即向toString
重载集添加函数。我没有看过Qt源,但似乎使用ADL执行了用于匹配名称以构造过载集的查找。
现在有了这个
struct Test {};
char *toString(const Test&);
它们位于相同的(全局)名称空间中。之所以行之有效,是因为使用ADL查找与Test
相关的名称会拉入全局命名空间,并且这就是toString
重载所在的位置。但这不同于
struct Test {};
namespace {
char *toString(const Test&);
}
因为后者与
相同struct Test {};
namespace someRandomUniqueIdentifier {
char *toString(const Test&);
}
using namespace someRandomUniqueIdentifier;
,因此当实例化类型为Test
的功能模板时,ADL未能找到toString
的名称,因为Test
在(未命名的)someRandomUniqueIdentifier
名称空间中未声明。如果您在匿名名称空间中定义Test
,则应调用适当的toString
函数。
您链接的线程是关于static
函数和匿名名称空间的。您遇到的问题与此无关,而是查找规则,尤其是ADL。