Глобальное распознавание функции не удалось

При наличии простого 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

Первый действительно вызывает функцию при сравнении объектов, второй нет!

Как упомянуто в этом заключении, не должно быть никакой разницы, кроме того, что анонимные пространства имен позволяют вам определять тип перевода-единицы-локальный. Ну, здесь, похоже, все наоборот.

1 ответ

Решение

По умолчанию 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;

и, следовательно, при создании экземпляра шаблона функции для типа TestADL не может найти toString назвать как Test не объявлен в (неназванном) someRandomUniqueIdentifier Пространство имен. Если вы определите Test внутри анонимного пространства имен, соответствующий toString функция должна быть вызвана.

Нить, на которую вы ссылаетесь static функции против анонимных пространств имен. Проблема, с которой вы сталкиваетесь, не связана с этим, это правила поиска, особенно ADL.

Другие вопросы по тегам