Skip to content

Can't format move-only ranges #3286

Description

@brevzin

Example:

#include <concepts>
#include <vector>
#include <fmt/ranges.h>

template <bool Copyable>
struct Vector {
    std::vector<int> v;

    Vector(std::initializer_list<int> elems) : v(elems) { }

    Vector(Vector&&) = default;
    Vector& operator=(Vector&&) = default;

    Vector(Vector const&) requires Copyable = default;
    Vector& operator=(Vector const&) requires Copyable = default;

    auto begin() { return v.begin(); }
    auto end() { return v.end(); }
};

static_assert(std::movable<Vector<false>>);
static_assert(std::movable<Vector<true>>);
static_assert(!std::copyable<Vector<false>>);
static_assert(std::copyable<Vector<true>>);

int main() {
    fmt::print("{}\n", Vector<true>{1, 2, 3});  // ok [1, 2, 3]
    fmt::print("{}\n", Vector<false>{1, 2, 3}); // error
}

This is because the range check for non-const ranges requires copyability and should probably just be removed (h/t @timsong-cpp):

fmt/include/fmt/ranges.h

Lines 154 to 159 in a2c05a1

template <typename T>
struct has_mutable_begin_end<
T, void_t<decltype(detail::range_begin(std::declval<T>())),
decltype(detail::range_end(std::declval<T>())),
enable_if_t<std::is_copy_constructible<T>::value>>>
: std::true_type {};

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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