diff --git a/CMakeLists.txt b/CMakeLists.txt index b096e4e2..ec7e14c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.8...3.25) +set(CMAKE_EXPORT_COMPILE_COMMANDS YES) + # Fallback for using newer policies on CMake <3.12. if(${CMAKE_VERSION} VERSION_LESS 3.12) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) diff --git a/test/std-test.cc b/test/std-test.cc index d12dbf5d..81d365a0 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -7,6 +7,7 @@ #include "fmt/std.h" +#include #include #include @@ -95,6 +96,28 @@ TEST(std_test, optional) { #endif } +// this struct exists only to force a variant to be +// valueless by exception +// NOLINTNEXTLINE +struct throws_on_move_t { + throws_on_move_t() = default; + + // NOLINTNEXTLINE + [[noreturn]] throws_on_move_t(throws_on_move_t&&) { + throw std::runtime_error{"Thrown by throws_on_move_t"}; + } + + throws_on_move_t(const throws_on_move_t&) = default; +}; + +template <> struct fmt::formatter : formatter { + template + auto format(const throws_on_move_t&, FormatContext& ctx) const { + string_view str{""}; + return formatter::format(str, ctx); + } +}; + TEST(std_test, variant) { #ifdef __cpp_lib_variant EXPECT_EQ(fmt::format("{}", std::monostate{}), "monostate"); @@ -126,6 +149,20 @@ TEST(std_test, variant) { volatile int i = 42; // Test compile error before GCC 11 described in #3068. EXPECT_EQ(fmt::format("{}", i), "42"); + + using V2 = std::variant; + + V2 v6{}; + + try { + throws_on_move_t thrower{}; + v6.emplace(std::move(thrower)); + } catch (const std::runtime_error&) { + } + // v6 is now valueless by exception + + EXPECT_EQ(fmt::format("{}", v6), "variant(valueless by exception)"); + #endif }