C перегрузка оператора вывода

#c #operator-overloading

#c #оператор-перегрузка

Вопрос:

У меня есть заголовочный файл, который выглядит следующим образом:

 #pragma once

//C   Output Streams
#include <iostream>

namespace microtask
{
    namespace log
    {
        /**
         * Severity level.
         */
        enum severity
        {
            debug,
            info,
            warning,
            error,
            critical
        };

        /**
         * Output the severity level.
         */
        std::ostreamamp; operator<<(std::ostreamamp; out, const severityamp; level);
    }
}
  

и исходный файл, который выглядит следующим образом:

 //Definitions
#include "severity.hpp"

//Namespaces
using namespace std;
using namespace microtask::log;

std::ostreamamp; operator<<(std::ostreamamp; out, const severityamp; level)
{
    switch(level)
    {
    case debug:
        out << "debug";
        break;
    case info:
        out << "info";
        break;
    case warning:
        out << "warning";
        break;
    case error:
        out << "error";
        break;
    case critical:
        out << "critical";
        break;
    default:
        out << "unknown";
        break;
    }

    return out;
}
  

что я пытаюсь скомпилировать в динамическую библиотеку. К сожалению, связывание завершается ошибкой с этим сообщением об ошибке:

 undefined reference to `microtask::log::operator<<(std::basic_ostream<char, std::char_traits<char> >amp;, microtask::log::severity constamp;)'
  

Что я делаю не так? Я проверил другие stackoverflow.com вопросы, которые казались похожими, но, насколько я могу судить, у меня правильный формат для перегрузки оператора.

Ответ №1:

В вашем файле .cpp не указывайте using , а вместо этого объявите правильное пространство имен:

 namespace microtask
{
    namespace log
    {
        ::std::ostream amp; operator<<(::std::ostreamamp; out, const severityamp; level)
        {
            // ...
        }
    }
}
  

На самом деле, не говорите using случайно вообще, если вы можете помочь этому. На мой взгляд, он должен быть зарезервирован для явного отображения базового элемента и запросов ADL.

Комментарии:

1. Что ж, это работает. Теперь, чтобы я снова не повторил ту же ошибку, почему это не работало раньше? (Я приму ваш ответ, как только истечет тайм-аут).

2. Вы определяли ::operator<< , а не microtask::log::operator<< . Это просто отдельная функция, и та, которая вам нужна, все еще отсутствует. Постоянное решение, за которое будут благодарны даже ваши внуки, — никогда не использовать using 🙂

3. ах, я понимаю, ну, это имеет смысл, я думаю. Idk, это просто сбило меня с толку, потому что я привык объявлять реализации для подобных методов класса.

4. @root.ctrlc Я считаю, что причина, по которой ваша версия не работает, заключается в том, что ваше определение operator<< в .cpp реализует ::operator<<(out, серьезность), но не microtask::log::operator<<(out, серьезность)

5. using предназначен, ну, для использования. Это не влияет на определение.