4

当有一个简单的 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

第一个在比较对象时确实调用了该函数,第二个没有!

正如这个结论中提到的,除了匿名命名空间允许您定义翻译单元本地类型之外,应该没有区别。好吧,这里看起来正好相反。

4

1 回答 1

2

默认QTest::toString实现是一个函数模板:

template <class T> char *QTest::toString(const T &value);

特化这个模板似乎是提供自定义实现的一种方法,但您正在使用另一种方法,即向toString重载集添加一个函数。我没有查看 Qt 源代码,但似乎查找匹配名称以构造重载集是使用 ADL 执行的。

现在当你有了这个

struct Test {};

char *toString(const Test&);

它们在同一个(全局)命名空间中。这是可行的,因为使用 ADL 来查找与Test全局命名空间中的 pull 相关的名称,而这就是您的toString重载所在的位置。但这不同于

struct Test {};

namespace {
    char *toString(const Test&);
}

因为后者与

struct Test {};

namespace someRandomUniqueIdentifier {
    char *toString(const Test&);
}

using namespace someRandomUniqueIdentifier;

因此,在为 type 实例化函数模板时Test,ADL 无法找到未在(未命名的)命名空间中声明的toString名称。如果您在匿名命名空间内定义,则应调用适当的函数。TestsomeRandomUniqueIdentifierTesttoString

您链接的线程是关于static函数与匿名名称空间的。您遇到的问题与此无关,它是查找规则,尤其是 ADL。

于 2019-03-21T10:30:57.573 回答