C ++ ADL функции в другом пространстве имен - PullRequest
1 голос
/ 20 мая 2019

У меня есть шаблон функции printSize, вызывающий перегруженную функцию getSize до объявления getSize.Для более ясной структуры моей программы я хотел бы поместить обе функции в разные пространства имен A и B, как показывают строки закомментированного кода.Однако ADL не сможет найти getSize.

На самом деле, printSize и getSize реализованы в разных заголовочных файлах.Поэтому я не могу поместить директиву using namespace.

#include <array>
#include <iostream>
#include <string>

namespace A {

template <typename T> struct tag {};

template <typename T>
void printSize(const T &data)
{
    size_t data_size = getSize(data, tag<T>{});
    //size_t data_size = B::getSize(data, tag<T>{});
    std::cout << "Size: " << data_size << std::endl;
}

//} // namespace A

//namespace B {

constexpr size_t getSize(const int &, tag<int>)
{
    return sizeof(int);
}

size_t getSize(const std::string &str, tag<std::string>)
{
    return str.size();
}

template <typename T, size_t N>
size_t getSize(const std::array<T, N> &array, tag<std::array<T, N>>)
{
    size_t array_size = 0;
    for (const T &element : array)
        array_size += getSize(element, tag<T>{});
    return array_size;
}

} // namespace A/B

int main()
{
    int a;
    A::printSize(a);

    std::array<std::string, 2> arr = {{"foo", "foobar"}};
    A::printSize(arr);

    return 0;
}

Есть ли способ заставить этот код компилироваться, если printSize и getSize определены в разных пространствах имен?

Ответы [ 2 ]

4 голосов
/ 20 мая 2019

Одним из решений было бы поместить тег в пространство имен B и перетащить его в A.

namespace B {
    template <typename T> struct tag {};
}

namespace A {
   using B::tag;
}

Теперь, поскольку tag происходит из пространства имен B, оно будет ассоциироваться с B для ADL.

1 голос
/ 20 мая 2019

Вы можете использовать объявление using, чтобы ввести имя из другого пространства имен.Например:

template <typename T>
void printSize(const T &data)
{
    using B::getSize;
    std::size_t data_size = getSize(data, tag<T>{});
    std::cout << "Size: " << data_size << std::endl;
}

getSize зависит от параметра шаблона T, поэтому ADL будет использоваться во второй фазе поиска (когда создается этот шаблон) для поиска других предоставленных getSize sпользователем.Здесь B::getSize должно быть объявлено до printSize, а само tag представляется избыточным.

...