Перегруженный оператор ostream << не работает с spdlog :: logger :: debug () - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть typedef над unordered_map из Eigen векторов и перегруженный оператор ostream <<:

namespace wolf{

typedef unordered_map<std::string, Eigen::VectorXd> VectorComposite;

std::ostream& operator <<(std::ostream &_os, const VectorComposite &_x)
{
    for (const auto &pair_key_vec : _x)
    {
        const auto &key = pair_key_vec.first;
        const auto &vec = pair_key_vec.second;
        _os << "\n  block(" << key << ") = \n" << vec;
    }
    return _os;
}

} // namespace wolf

Я могу заставить этот оператор работать для стандартных std::cout,

VectorComposite x;
x.emplace("P", Vector2d(1,1));
x.emplace("O", Vector3d(2,2,2));

cout << "x = " << x << endl;

выдает хороший результат, как и ожидалось:

x = 
  block(O) = 
2
2
2
  block(P) = 
1
1

Однако, когда я пытаюсь использовать spdlog методы ведения журнала, такие как debug(), я получаю ошибки компиляции. Поскольку реализация spdlog представляет собой шаблон variadi c, мне трудно отладить проблему. Я стараюсь указывать c:

Вот мой вызов spdlog, через собственный определенный макрос

WOLF_DEBUG("x = " , x);

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

Вот макрос расширения:

  #define WOLF_DEBUG(...) wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_).debug(__VA_ARGS__);

это длинная строка , включая несвязанные вопросы, такие как синглтон. Важной частью является определение __VA_ARGS__, переданного функции debug().

Вот наша реализация debug(__VA_ARGS__) в строке выше, которая теперь вызывает по очереди spdlog::debug()

template<typename... Args>
void Logger::debug(Args&&... args) const
{
  console_->debug(std::get<sizeof...(args)-1>(repeated_brace), std::forward<Args>(args)...);
}

Чтобы иметь дело с переменным числом аргументов, переменная repeated_brace - это способ передать определенное количество фигурных скобок, т.е.

static const auto repeated_brace = std::make_tuple("{}",
                                                   "{}{}",
                                                   "{}{}{}",
                                                   "{}{}{}{}",
                                                   "{}{}{}{}{}",
                                                   "{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}"); // up to 25 args. Should be fine

, где в нашем случае я думаю, что одна или две повторяющиеся фигурные скобки debug(...).

Наконец, вот определение spdlog::logger::debug() метода в spdlog/details/logger_impl.h строке 130

template <typename Arg1, typename... Args>
inline void spdlog::logger::debug(const char* fmt, const Arg1 &arg1, const Args&... args)
{
    log(level::debug, fmt, arg1, args...);
}

Я прошу прощения за длинное объяснение, но с вариади c Я полностью запутался в том, какие аргументы наконец передаются в функцию spdlog::logger::debug(), поэтому я не знаю, как на самом деле отлаживать это. Я надеюсь, что вы, ребята, сможете это понять.

Мне кажется, что ошибка может быть связана с тем, что мы используем typedef в качестве объекта для печати. У нас есть аналог operator<< для класса MatrixComposite, который похож на VectorComposite, который отлично работает как с std::cout, так и с spdlog::...::debug().

Компилятор жалуется на следующий стек сообщений об ошибках :

/usr/local/include/spdlog/fmt/bundled/ostream.h:90:12: error: invalid operands to binary expression ('std::basic_ostream<char>' and 'const std::__1::unordered_map<std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, std::__1::hash<std::__1::basic_string<char> >, std::__1::equal_to<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > > >')
    output << value;
    ~~~~~~ ^  ~~~~~
/usr/local/include/spdlog/fmt/bundled/format.h:1401:9: note: in instantiation of function template specialization 'fmt::format<char, fmt::ArgFormatter<char>, std::__1::unordered_map<std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, std::__1::hash<std::__1::basic_string<char> >, std::__1::equal_to<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > > > >' requested here
        format(*static_cast<Formatter*>(formatter),
        ^
/usr/local/include/spdlog/fmt/bundled/format.h:1503:26: note: in instantiation of function template specialization 'fmt::internal::MakeValue<fmt::BasicFormatter<char, fmt::ArgFormatter<char> > >::format_custom_arg<std::__1::unordered_map<std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, std::__1::hash<std::__1::basic_string<char> >, std::__1::equal_to<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > > > >' requested here
        custom.format = &format_custom_arg<T>;
                         ^
/usr/local/include/spdlog/fmt/bundled/format.h:2496:20: note: in instantiation of function template specialization 'fmt::internal::MakeValue<fmt::BasicFormatter<char, fmt::ArgFormatter<char> > >::MakeValue<std::__1::unordered_map<std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, std::__1::hash<std::__1::basic_string<char> >, std::__1::equal_to<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > > > >' requested here
    Value result = MakeValue<Formatter>(value);
                   ^
/usr/local/include/spdlog/fmt/bundled/format.h:2922:5: note: in instantiation of function template specialization 'fmt::internal::ArgArray<2, true>::make<fmt::BasicFormatter<char, fmt::ArgFormatter<char> >, std::__1::unordered_map<std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, std::__1::hash<std::__1::basic_string<char> >, std::__1::equal_to<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > > > >' requested here
    FMT_VARIADIC_VOID(write, BasicCStringRef<Char>)
    ^
/usr/local/include/spdlog/fmt/bundled/format.h:2565:26: note: expanded from macro 'FMT_VARIADIC_VOID'
      ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
                         ^
/usr/local/include/spdlog/details/logger_impl.h:69:21: note: in instantiation of function template specialization 'fmt::BasicWriter<char>::write<char [5], std::__1::unordered_map<std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, std::__1::hash<std::__1::basic_string<char> >, std::__1::equal_to<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > > > >' requested here
        log_msg.raw.write(fmt, args...);
                    ^
/usr/local/include/spdlog/details/logger_impl.h:133:5: note: in instantiation of function template specialization 'spdlog::logger::log<char [5], std::__1::unordered_map<std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, std::__1::hash<std::__1::basic_string<char> >, std::__1::equal_to<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > > > >' requested here
    log(level::debug, fmt, arg1, args...);
    ^
/Users/jsola/dev/wolf_lib/core/include/core/utils/logging.h:179:13: note: in instantiation of function template specialization 'spdlog::logger::debug<char [5], std::__1::unordered_map<std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, std::__1::hash<std::__1::basic_string<char> >, std::__1::equal_to<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > > > >' requested here
  console_->debug(std::get<sizeof...(args)-1>(repeated_brace), std::forward<Args>(args)...);
            ^
/Users/jsola/dev/wolf_lib/core/test/gtest_state_composite.cpp:331:5: note: in instantiation of function template specialization 'wolf::internal::do_not_enter_where_the_wolf_lives::Logger::debug<char const (&)[5], std::__1::unordered_map<std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, std::__1::hash<std::__1::basic_string<char> >, std::__1::equal_to<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > > > &>' requested here
    WOLF_DEBUG("x = " , x);
    ^
/Users/jsola/dev/wolf_lib/core/include/core/utils/logging.h:315:94: note: expanded from macro 'WOLF_DEBUG'
  #define WOLF_DEBUG(...) wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_).debug(__VA_ARGS__);
...