Аргумент Зависимый поиск и перегрузка потоковых операторов - PullRequest
0 голосов
/ 24 января 2020

У меня есть библиотека, которая представляет какой-то контейнер struct, в котором я хочу собирать различные типы универсальных c данных, которые могут быть из того же namespace библиотеки, а также данные из std пространство имен, такое как array или tuple или pairs.

В этом контейнере есть метод print_all, который вызовет operator<< для всех элементов в контейнере. Предполагается, что такой оператор должен быть предоставлен пользователем библиотеки.

Тестируя библиотеку, я использую различные параметры шаблона для T, но меня не особо волнует, что печатается print_all метод. Для целей тестирования меня волнует только то, что печатается пример символа независимо от того, какой T тестируется. На самом деле, я использую Google Test Framework и использую Google Test Framework, и поведение тестируемого метода действительно одинаково для каждого предоставленного типа данных.

Я пытался предоставить обе версии c generi. operator<< и двух указанных c версий. Вы можете видеть их между директивой #if. Ни одна из двух веток компиляции не компилируется правильно, скорее всего из-за какого-то нарушения правил поиска Кенига. Но в любом случае то, что я хочу сделать, должно быть легко как-то возможно. Чего мне не хватает?

Вот пример кода:

#include <algorithm>
#include <iostream>
#include <vector>

namespace my
{
template<typename DataType>
struct Container
{
    void print_all( std::ostream& os ) const
    {
        std::for_each(std::begin(data),
                      std::end(data),
                      [&os](const DataType& value)
                      {
                          os << value;
                      });
    }

    std::vector<DataType> data;
};

namespace test
{
struct Data
{
    std::byte data[4];
};

using Array = std::array<std::byte,4>;

#if 0

template<typename T>
std::ostream& operator<<(std::ostream& os, const T& data)
{
    return os << 'X';
}

#else

std::ostream& operator<<(std::ostream& os, const Data& data)
{
    return os << 'X';
}

std::ostream& operator<<(std::ostream& os, const Array& data)
{
    return os << 'X';
}

#endif

void run()
{  
    // Test with custom data
    { 
        Container< Data> container;
        container.data.resize(1);
        container.print_all( std::cout );
    }
    // Test with std data
    {
        Container< Array> container;
        container.data.resize(1);
        container.print_all( std::cout );
    }
}

} // namespace test
} // namespace my

int main()
{
    my::test::run();
    return 0;
}

1 Ответ

2 голосов
/ 24 января 2020

ADL просматривает пространства имен, связанные с аргументами.

using Array = std::array<std::byte,4>;

этот тип test::Array является псевдонимом. Пространства имен, связанные с ним для целей ADL, равны std. test не связано с этим. ADL будет смотреть только в std. Вам не разрешено добавлять операторы в std; если вы нарушите это, ваша программа будет плохо сформирована, диагностика c не требуется. ADL не может помочь вам, потому что он помогает только людям, которым принадлежат пространства имен, связанные с аргументами.

Любой <<, который вы хотите поддерживать в std, должен быть в namespace my, определенном ранее. Ваша print_all функция.

Ваш код для Data выглядит мне так, как будто он работает, я предполагаю, что ваш вопрос был просто плохо написан, поскольку подразумевает, что os <<Data не работает. Если я ошибаюсь, и это не работает, это из-за некоторой опечатки; ADL отлично работает на struct s, но не на псевдонимах. В будущем, пожалуйста, включайте полные сообщения об ошибках, когда код не работает.

...