Повысить регрессию библиотеки журналов 1.73 - PullRequest
1 голос
/ 02 мая 2020

Я недавно обновился с Boost 1.72 до 1.73. По какой-то причине в библиотеке boost :: log наблюдается некоторая регрессия, и я не могу найти решение, просматривая исходный код и исследуя примеры программных ошибок из предыдущей версии 1.72. Включение следующего заголовка, по-видимому, является источником ошибок.

#include <boost/log/support/date_time.hpp>

Включение вышеперечисленного вызывает следующие запутанные выходные данные компилятора в Visual Studio 2019 (x64).

1>------ Build started: Project: util, Configuration: Debug x64 ------
1>Logger.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\utility(151,1): error C2220: the following warning is treated as an error
1>C:\Users\johnc\main\extlibs\boost_1_73_0\boost\date_time\date_parsing.hpp(111): message : see reference to function template instantiation 'std::pair<const std::string,unsigned short>::pair<const char(&)[4],int,0>(_Other1,_Other2 &&) noexcept(false)' being compiled
1>        with
1>        [
1>            _Other1=const char (&)[4],
1>            _Other2=int
1>        ]
1>C:\Users\johnc\main\extlibs\boost_1_73_0\boost\date_time\date_parsing.hpp(98): message : see reference to function template instantiation 'std::pair<const std::string,unsigned short>::pair<const char(&)[4],int,0>(_Other1,_Other2 &&) noexcept(false)' being compiled
1>        with
1>        [
1>            _Other1=const char (&)[4],
1>            _Other2=int
1>        ]
1>C:\Users\johnc\main\extlibs\boost_1_73_0\boost\date_time\date_parsing.hpp(168): message : see reference to function template instantiation 'unsigned short boost::date_time::month_str_to_ushort<month_type>(const std::string &)' being compiled
1>C:\Users\johnc\main\extlibs\boost_1_73_0\boost\date_time\gregorian\parsers.hpp(49): message : see reference to function template instantiation 'date_type boost::date_time::parse_date<boost::gregorian::date>(const std::string &,int)' being compiled
1>        with
1>        [
1>            date_type=boost::gregorian::date
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\utility(151,1): warning C4244: 'initializing': conversion from '_Ty' to '_Ty2', possible loss of data
1>        with
1>        [
1>            _Ty=int
1>        ]
1>        and
1>        [
1>            _Ty2=unsigned short
1>        ]
1>Done building project "util.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Глядя на utility(151,1) Я вижу следующий запутанный метапрограммирующий код (в моем случае _HAS_CONDITIONAL_EXPLICIT включен по умолчанию)

#if _HAS_CONDITIONAL_EXPLICIT
    template <class _Other1, class _Other2,
        enable_if_t<conjunction_v<is_constructible<_Ty1, _Other1>, is_constructible<_Ty2, _Other2>>, int> = 0>
    constexpr explicit(!is_convertible_v<_Other1, _Ty1> || !is_convertible_v<_Other2, _Ty2>)
        pair(_Other1&& _Val1, _Other2&& _Val2) noexcept(
            is_nothrow_constructible_v<_Ty1, _Other1>&& is_nothrow_constructible_v<_Ty2, _Other2>) // strengthened
        : first(_STD forward<_Other1>(_Val1)), second(_STD forward<_Other2>(_Val2)) {}
#else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv

Похоже, проблема возникла date_parsing.hpp, где он инициализирует stati c std :: map пар.

#else  //c+11 and beyond
        static std::map<std::string, unsigned short> month_map =
          { { "jan", 1 },  { "january", 1 },
            { "feb", 2 },  { "february", 2 },
            { "mar", 3 },  { "march", 3 },
            { "apr", 4 },  { "april", 4 },
            { "may", 5 },
            { "jun", 6 },  { "june", 6 },
            { "jul", 7 },  { "july", 7 },
            { "aug", 8 },  { "august", 8 },
            { "sep", 9 },  { "september", 9 },
            { "oct", 10 }, { "october", 10 },
            { "nov", 11 }, { "november", 11 },
            { "dec", 12 }, { "december", 12 }
          };
#endif
        std::map<std::string, unsigned short>::const_iterator mitr = month_map.find( str );
        if ( mitr !=  month_map.end() ) {
          return mitr->second;
        }

Вот так я использую библиотеку. См. Ниже закомментированный код временной отметки и присвоение форматера (в дополнение к удалению ошибочного включения), чтобы получить исходный код для компиляции.

/*static*/
void
Logger::init(const std::map<std::string, fs::path>& rLogInfo)
{
    // Construct the sink for the "event" channel.
    // C++17 structured bindings.
    for (const auto& [rChannelName, rLogPath] : rLogInfo) {
        // empty path=>syslog entry
        if (!rChannelName.empty()) {
            if (!rLogPath.empty()) {
                //static const auto gFormatter = expr::format("%1% [%2%] tid[%3%] %4%")
                //    % expr::format_date_time<boost::posix_time::ptime>("TimeStamp", "%H:%M:%S.%f")
                //    % logging::trivial::severity
                //    % expr::attr<attrs::current_thread_id::value_type>("ThreadID")
                //    % expr::smessage;
                using text_sink = sinks::synchronous_sink<sinks::text_ostream_backend>;
                auto sink = boost::make_shared<text_sink>();
                sink->locked_backend()->auto_flush(true);
                sink->locked_backend()->add_stream(
                    boost::make_shared<std::ofstream>(rLogPath));
                //sink->set_formatter(gFormatter);
                sink->set_filter(expr::attr<std::string>("Channel") == rChannelName);
                logging::core::get()->add_sink(std::move(sink));
            } else { // syslog entry - time-stamp not required
                static const auto gFormatter = expr::format("[%1%] tid[%2%] %3%")
                    % logging::trivial::severity
                    % expr::attr<attrs::current_thread_id::value_type>("ThreadID")
                    % expr::smessage;
                using sink_t = sinks::synchronous_sink<sinks::syslog_backend>;
                // Create a new backend
#if defined (_WIN32)
                auto backend = boost::make_shared<sinks::syslog_backend>(
                    keywords::use_impl = sinks::syslog::udp_socket_based,
                    keywords::facility = sinks::syslog::local7);
                backend->set_target_address("localhost", 514);
#else
                // Create a backend
                auto backend = boost::make_shared<sinks::syslog_backend>(
                    keywords::use_impl = sinks::syslog::native,
                    keywords::facility = sinks::syslog::local7);
#endif
                // We'll have to map our custom levels to the syslog levels
                sinks::syslog::custom_severity_mapping<trivial::severity_level> mapping("Severity");
                mapping[trivial::debug] = sinks::syslog::debug;
                mapping[trivial::info] = sinks::syslog::info;
                mapping[trivial::warning] = sinks::syslog::warning;
                mapping[trivial::error] = sinks::syslog::error;
                mapping[trivial::fatal] = sinks::syslog::critical;
                backend->set_severity_mapper(mapping);

                // Wrap it into the frontend and register in the core.
                auto sink = boost::make_shared<sink_t>(backend);
                sink->set_formatter(gFormatter);
                sink->set_filter(expr::attr<std::string>("Channel") == rChannelName);
                logging::core::get()->add_sink(std::move(sink));
            }
        }
    }
    // register common attributes - ThreadID, LineID, TimeStamp etc.
    logging::add_common_attributes();
}
...