diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index d2df2bc3..95d3de87 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -13,7 +13,6 @@ check_submodule(spdlog spdlog) # See https://github.com/gabime/spdlog/issues/1190 set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(SPDLOG_USE_STD_FORMAT ${KNUT_USE_STD_FORMAT}) add_subdirectory(spdlog) # nlohmann/json diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e4497a6..2666e34d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,6 @@ include(InstallDependency) include(CheckSubmodule) option(USE_ASAN "use Address Sanitizer" OFF) -option(KNUT_USE_STD_FORMAT "Use std format library for speed log library" ON) # It's best practice to only enable -Werror in CI & development builds. # We enable this option in the appropriate CMakePresets. # If you just want to have a working build of knut, -Werror can be very annoying, so keep it off by default. diff --git a/CMakePresets.json b/CMakePresets.json index 2fc6e3a6..9036ff50 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -45,8 +45,7 @@ "generator": "Ninja", "cacheVariables": { "CMAKE_BUILD_TYPE": "RelWithDebInfo", - "KNUT_ERROR_ON_WARN": "ON", - "KNUT_USE_STD_FORMAT": "OFF" + "KNUT_ERROR_ON_WARN": "ON" } }, { diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 41cc8a48..86d7dd96 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -10,13 +10,8 @@ project(knut-utils LANGUAGES CXX) find_package(Qt6 REQUIRED COMPONENTS Core Gui) -set(PROJECT_SOURCES json.h qt_fmt_helpers.h strings.h strings.cpp log.h) +set(PROJECT_SOURCES json.h qt_fmt_helpers.h qt_fmt_format.h strings.h strings.cpp log.h) add_library(${PROJECT_NAME} STATIC ${PROJECT_SOURCES}) -if(KNUT_USE_STD_FORMAT) - target_sources(${PROJECT_NAME} PUBLIC qt_std_format.h) -else() - target_sources(${PROJECT_NAME} PUBLIC qt_fmt_format.h) -endif() target_link_libraries(${PROJECT_NAME} PUBLIC nlohmann_json::nlohmann_json spdlog::spdlog Qt6::Core Qt6::Gui) diff --git a/src/utils/qt_std_format.h b/src/utils/qt_std_format.h deleted file mode 100644 index b4f1b3d3..00000000 --- a/src/utils/qt_std_format.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file is part of KDToolBox. - - SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company - - SPDX-License-Identifier: MIT -*/ - -#pragma once - -#if __cplusplus < 202002L -#error "This header requires C++20" -#endif - -#include "qt_fmt_helpers.h" - -#include -#include - -namespace Qt_fmt::detail { -template -concept IsFormattableViaQDebug = requires(QDebug &d, const T &t) { - d << t; - requires !Qt_fmt::exclude_from_qdebug_fmt::value; -}; -} - -template - requires Qt_fmt::detail::IsFormattableViaQDebug -struct std::formatter -{ - template - constexpr auto parse(ParseContext &ctx) - { - auto it = ctx.begin(); - auto end = ctx.end(); - if (it != end && *it != '}') - throw std::format_error("Only {} is supported"); - return it; - } - - template - auto format(const T &t, FormatContext &ctx) const - { - // See the comment in the libfmt formatter - QString buffer; - QDebug debug(&buffer); - debug.noquote().nospace() << t; - return std::format_to(ctx.out(), "{}", buffer.toStdString()); - } -}; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f6f2ee1e..4ea7b760 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -49,13 +49,6 @@ add_knut_test(tst_client tst_client.cpp knut-lsp) add_knut_test(tst_settings tst_settings.cpp) -# tst_qt_std_format tests qt_format with std::format -# However, std::format isn't currently well-supported by the major compilers. -# So for now, disable this test. It can be reenabled once we can finally switch to std::format -# add_knut_test(tst_qt_std_format tst_qt_std_format.cpp) -# Use the fmt library that's bundled with spdlog instead. -add_knut_test(tst_qt_fmt_format tst_qt_fmt_format.cpp) - add_knut_test(tst_stringutils tst_stringutils.cpp) add_knut_test(tst_textdocument tst_textdocument.cpp) diff --git a/tests/tst_qt_fmt_format.cpp b/tests/tst_qt_fmt_format.cpp deleted file mode 100644 index edf01dfd..00000000 --- a/tests/tst_qt_fmt_format.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - This file is part of Knut. - - SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company - - SPDX-License-Identifier: GPL-3.0-only - - Contact KDAB at for commercial licensing options. -*/ - -/* - This file is part of KDToolBox. - - SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company - - SPDX-License-Identifier: MIT -*/ - -#include "utils/qt_fmt_format.h" - -#include -#include -#include -#include -#include -#include -#include - -class QtFmtFormatTest : public QObject -{ - Q_OBJECT - -private Q_SLOTS: - void testQtFmtFormat(); -}; - -// Custom class streamable via QDebug -class CustomClass -{ -}; -QDebug operator<<(QDebug d, CustomClass) -{ - return d << "CustomClass()"; -} - -// Custom class streamable via fmt::formatBothFmtAndQDebugClass and QDebug -class BothFmtAndQDebugClass -{ -}; -template <> -struct fmt::formatter -{ - template - constexpr auto parse(ParseContext &ctx) - { - auto it = ctx.begin(); - auto end = ctx.end(); - if (it != end && *it != '}') - throw fmt::format_error("Only {} is supported"); - return it; - } - template - auto format(const BothFmtAndQDebugClass &, FormatContext &ctx) const - { - return fmt::format_to(ctx.out(), "BothFmtAndQDebugClass via std"); - } -}; - -QDebug operator<<(QDebug d, BothFmtAndQDebugClass) -{ - return d << "BothFmtAndQDebugClass via QDebug"; -} - -template <> -struct Qt_fmt::exclude_from_qdebug_fmt : std::true_type -{ -}; - -void QtFmtFormatTest::testQtFmtFormat() -{ - // This is a bit sketchy because it depends on QDebug's format. Better than nothing? - using namespace fmt::literals; - - // Fundamental / Standard Library types supported by fmt::format _and_ QDebug; - // should all go through fmt::format - QCOMPARE(fmt::format("{}", 42), "42"); - QCOMPARE(fmt::format("{}", 10.5), "10.5"); - QCOMPARE(fmt::format("{}", "hello"), "hello"); - QCOMPARE(fmt::format("{}", (const char *)"hello"), "hello"); - - QCOMPARE(fmt::format("{}", std::string("hello")), "hello"); - QCOMPARE(fmt::format("{}", std::string_view("hello")), "hello"); - - // Qt types - QCOMPARE(fmt::format("{}", QStringLiteral("hello")), "hello"); - QCOMPARE(fmt::format("{}", QByteArray("hello")), "hello"); - QCOMPARE(fmt::format("{}", QDateTime(QDate(2000, 2, 29), QTime(12, 12, 12), Qt::UTC)), - "QDateTime(2000-02-29 12:12:12.000 UTC Qt::UTC)"); - QCOMPARE(fmt::format("{}", QUuid()), "QUuid({00000000-0000-0000-0000-000000000000})"); - QCOMPARE(fmt::format("{}", QRect()), "QRect(0,0 0x0)"); - QCOMPARE(fmt::format("{}", QSizeF()), "QSizeF(-1, -1)"); - - // Q_FLAG / Q_ENUM - QCOMPARE(fmt::format("{}", Qt::Alignment(Qt::AlignLeft | Qt::AlignVCenter)), - "QFlags(AlignLeading|AlignVCenter)"); - QCOMPARE(fmt::format("{}", Qt::AlignLeft), "Qt::AlignLeft"); - - // User defined types - QCOMPARE(fmt::format("{}", CustomClass()), "CustomClass()"); - QCOMPARE(fmt::format("{}", BothFmtAndQDebugClass()), "BothFmtAndQDebugClass via std"); -} - -// static_assert(Qt_fmt::detail::IsFormattableViaQDebug); -// static_assert(Qt_fmt::detail::IsFormattableViaQDebug); -// static_assert(Qt_fmt::detail::IsFormattableViaQDebug); -// static_assert(Qt_fmt::detail::IsFormattableViaQDebug); -// static_assert(Qt_fmt::detail::IsFormattableViaQDebug); - -QTEST_APPLESS_MAIN(QtFmtFormatTest) - -#include "tst_qt_fmt_format.moc" diff --git a/tests/tst_qt_std_format.cpp b/tests/tst_qt_std_format.cpp deleted file mode 100644 index 3d88dc19..00000000 --- a/tests/tst_qt_std_format.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - This file is part of Knut. - - SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company - - SPDX-License-Identifier: GPL-3.0-only - - Contact KDAB at for commercial licensing options. -*/ - -/* - This file is part of KDToolBox. - - SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company - - SPDX-License-Identifier: MIT -*/ - -#include "utils/qt_std_format.h" - -#include -#include -#include -#include -#include -#include -#include - -class QtStdFormatTest : public QObject -{ - Q_OBJECT - -private Q_SLOTS: - void testQtStdFormat(); -}; - -// Custom class streamable via QDebug -class CustomClass -{ -}; -QDebug operator<<(QDebug d, CustomClass) -{ - return d << "CustomClass()"; -} - -// Custom class streamable via std::formatBothStdAndQDebugClass and QDebug -class BothStdAndQDebugClass -{ -}; -template <> -struct std::formatter -{ - template - constexpr auto parse(ParseContext &ctx) - { - auto it = ctx.begin(); - auto end = ctx.end(); - if (it != end && *it != '}') - throw std::format_error("Only {} is supported"); - return it; - } - template - auto format(const BothStdAndQDebugClass &, FormatContext &ctx) const - { - return std::format_to(ctx.out(), "BothStdAndQDebugClass via std"); - } -}; - -QDebug operator<<(QDebug d, BothStdAndQDebugClass) -{ - return d << "BothStdAndQDebugClass via QDebug"; -} - -template <> -struct Qt_fmt::exclude_from_qdebug_fmt : std::true_type -{ -}; - -void QtStdFormatTest::testQtStdFormat() -{ - // This is a bit sketchy because it depends on QDebug's format. Better than nothing? - using namespace std::literals; - - // Fundamental / Standard Library types supported by std::format _and_ QDebug; - // should all go through std::format - QCOMPARE(std::format("{}", 42), "42"); - QCOMPARE(std::format("{}", 10.5), "10.5"); - QCOMPARE(std::format("{}", "hello"), "hello"); - QCOMPARE(std::format("{}", (const char *)"hello"), "hello"); - - QCOMPARE(std::format("{}", "hello"s), "hello"); - QCOMPARE(std::format("{}", "hello"sv), "hello"); - - // Qt types - QCOMPARE(std::format("{}", QStringLiteral("hello")), "hello"); - QCOMPARE(std::format("{}", QByteArray("hello")), "hello"); - QCOMPARE(std::format("{}", QDateTime(QDate(2000, 2, 29), QTime(12, 12, 12), Qt::UTC)), - "QDateTime(2000-02-29 12:12:12.000 UTC Qt::UTC)"); - QCOMPARE(std::format("{}", QUuid()), "QUuid({00000000-0000-0000-0000-000000000000})"); - QCOMPARE(std::format("{}", QRect()), "QRect(0,0 0x0)"); - QCOMPARE(std::format("{}", QSizeF()), "QSizeF(-1, -1)"); - - // Q_FLAG / Q_ENUM - QCOMPARE(std::format("{}", Qt::Alignment(Qt::AlignLeft | Qt::AlignVCenter)), - "QFlags(AlignLeading|AlignVCenter)"); - QCOMPARE(std::format("{}", Qt::AlignLeft), "Qt::AlignLeft"); - - // User defined types - QCOMPARE(std::format("{}", CustomClass()), "CustomClass()"); - QCOMPARE(std::format("{}", BothStdAndQDebugClass()), "BothStdAndQDebugClass via std"); -} - -static_assert(Qt_fmt::detail::IsFormattableViaQDebug); -static_assert(Qt_fmt::detail::IsFormattableViaQDebug); -static_assert(Qt_fmt::detail::IsFormattableViaQDebug); -static_assert(Qt_fmt::detail::IsFormattableViaQDebug); -static_assert(Qt_fmt::detail::IsFormattableViaQDebug); - -QTEST_APPLESS_MAIN(QtStdFormatTest) - -#include "tst_qt_std_format.moc"