全局功能识别失败

时间:2019-03-21 10:10:04

标签: c++ c++11 qtest

使用简单的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所述,除了匿名名称空间允许您定义本地翻译单元类型之外,应该没有其他区别。好吧,这看起来恰恰相反。

1 个答案:

答案 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。