Skip to content

Module version can't compile fmt::join<std::string_view> #4379

@Algunenano

Description

@Algunenano

Minimal repro:

Building with:

  • clang 19.1.7. Also reproduces with gcc 14.2.1
  • ninja 1.12.1
  • cmake 3.31.6

Minimal cmake project to reproduce: proj.zip

Files inside (just in case):
CMakeLists.txt:

cmake_minimum_required(VERSION 3.30 FATAL_ERROR)

set(CMAKE_CXX_STANDARD 23)

project(main LANGUAGES CXX)

add_executable(main main.cpp)

include(FetchContent)
FetchContent_Declare(
        fmt
        GIT_REPOSITORY https://github.com/fmtlib/fmt
        GIT_TAG        123913715afeb8a437e6388b4473fcc4753e1c9a) # 11.1.4
FetchContent_MakeAvailable(fmt)


# Comment to disable fmt module

target_sources(main
        PUBLIC FILE_SET CXX_MODULES
        FILES
        ${fmt_SOURCE_DIR}/src/fmt.cc
)
target_include_directories(main PRIVATE ${fmt_SOURCE_DIR}/include)


# Uncomment for header only
# target_link_libraries(main PRIVATE fmt::fmt-header-only)
#include <string>
#include <vector>

import fmt;
// #include <fmt/format.h>
// #include <fmt/ranges.h>


int main(int argc, char* argv[])
{
    std::vector<std::string> strings { "AAA", "BBB", "CCC" };
    std::vector<std::string_view> svs;

    for (size_t i = 0; i < strings.size(); ++i)
        svs.emplace_back(strings[i]);

    fmt::print("{}\n", fmt::join(svs, ", "));
    return 0;
}
$ mkdir build
$ cd build/
$ CC=clang CXX=clang++ cmake .. -DCMAKE_GENERATOR=Ninja
-- The CXX compiler identification is Clang 19.1.7
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/lib/ccache/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Cloning into 'fmt-src'...
HEAD is now at 12391371 Update version
-- {fmt} version: 11.1.4
-- Build type: 
-- Performing Test HAS_NULLPTR_WARNING
-- Performing Test HAS_NULLPTR_WARNING - Success
-- Configuring done (4.4s)
-- Generating done (0.0s)
-- Build files have been written to: /tmp/other/proj/build
$ ninja
[8/9] Building CXX object CMakeFiles/main.dir/main.cpp.o
FAILED: CMakeFiles/main.dir/main.cpp.o 
/usr/lib/ccache/bin/clang++  -I/tmp/other/proj/build/_deps/fmt-src/include -std=gnu++23 -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d @CMakeFiles/main.dir/main.cpp.o.modmap -o CMakeFiles/main.dir/main.cpp.o -c /tmp/other/proj/main.cpp
In module 'fmt' imported from /tmp/other/proj/main.cpp:4:
/tmp/other/proj/build/_deps/fmt-src/include/fmt/base.h:2235:45: error: implicit instantiation of undefined template 'fmt::detail::type_is_unformattable_for<fmt::join_view<__gnu_cxx::__normal_iterator<std::basic_string_view<char> *, std::vector<std::basic_string_view<char>>>, __gnu_cxx::__normal_iterator<std::basic_string_view<char> *, std::vector<std::basic_string_view<char>>>>, char>'
 2235 |     type_is_unformattable_for<T, char_type> _;
      |                                             ^
/tmp/other/proj/build/_deps/fmt-src/include/fmt/base.h:2208:44: note: in instantiation of function template specialization 'fmt::detail::value<fmt::context>::value<fmt::join_view<__gnu_cxx::__normal_iterator<std::basic_string_view<char> *, std::vector<std::basic_string_view<char>>>, __gnu_cxx::__normal_iterator<std::basic_string_view<char> *, std::vector<std::basic_string_view<char>>>>, 0>' requested here
 2208 |   FMT_CONSTEXPR20 FMT_INLINE value(T& x) : value(x, custom_tag()) {}
      |                                            ^
/tmp/other/proj/build/_deps/fmt-src/include/fmt/base.h:2913:22: note: in instantiation of function template specialization 'fmt::detail::value<fmt::context>::value<fmt::join_view<__gnu_cxx::__normal_iterator<std::basic_string_view<char> *, std::vector<std::basic_string_view<char>>>, __gnu_cxx::__normal_iterator<std::basic_string_view<char> *, std::vector<std::basic_string_view<char>>>>, 0>' requested here
 2913 |   vargs<T...> va = {{args...}};
      |                      ^
/tmp/other/proj/main.cpp:17:10: note: in instantiation of function template specialization 'fmt::print<fmt::join_view<__gnu_cxx::__normal_iterator<std::basic_string_view<char> *, std::vector<std::basic_string_view<char>>>, __gnu_cxx::__normal_iterator<std::basic_string_view<char> *, std::vector<std::basic_string_view<char>>>>>' requested here
   17 |     fmt::print("{}\n", fmt::join(svs, ", "));
      |          ^
/tmp/other/proj/build/_deps/fmt-src/include/fmt/base.h:2075:45: note: template is declared here
 2075 | template <typename T, typename Char> struct type_is_unformattable_for;
      |                                             ^
1 error generated.
ninja: build stopped: subcommand failed.

Note that this works fine if:

  • fmt::join is used with std::string instead of std::string_view (replace fmt::join(svs, ", ") with fmt::join(strings, ", "))
  • The non-module version (header only or library) is used (edit CMakeLists.txt and main.cpp to use the default build instead of a module).

That is, it only fails when using both std::string_view and the module build. It happens with other range iterators, like std::unordered_map and so on.

I though it might be some missing export but I can't find what's missing.

Simple patch to change from module to non-module version:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 60cf589..69c6acb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,13 +16,13 @@ FetchContent_MakeAvailable(fmt)
 
 # Comment to disable fmt module
 
-target_sources(main
-        PUBLIC FILE_SET CXX_MODULES
-        FILES
-        ${fmt_SOURCE_DIR}/src/fmt.cc
-)
-target_include_directories(main PRIVATE ${fmt_SOURCE_DIR}/include)
+# target_sources(main
+#         PUBLIC FILE_SET CXX_MODULES
+#         FILES
+#         ${fmt_SOURCE_DIR}/src/fmt.cc
+# )
+# target_include_directories(main PRIVATE ${fmt_SOURCE_DIR}/include)
 
 
 # Uncomment for header only
-# target_link_libraries(main PRIVATE fmt::fmt-header-only)
+target_link_libraries(main PRIVATE fmt::fmt-header-only)
diff --git a/main.cpp b/main.cpp
index 6b5fb4e..4c06e60 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,9 +1,9 @@
 #include <string>
 #include <vector>
 
-import fmt;
-// #include <fmt/format.h>
-// #include <fmt/ranges.h>
+// import fmt;
+#include <fmt/format.h>
+#include <fmt/ranges.h>
 
 
 int main(int argc, char* argv[])

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions