Skip to content

Commit b817610

Browse files
authored
Check range_begin is dereferenceable (#3964)
Fixes issue #3839 An Eigen 3.4 2x2 matrix has a begin member function that returns void Be more strict checking that the result of calling *begin() is valid See input_or_output_iterator concept notes about void
1 parent 706eabd commit b817610

File tree

2 files changed

+12
-6
lines changed

2 files changed

+12
-6
lines changed

Diff for: include/fmt/ranges.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ template <typename T, typename Enable = void>
6868
struct has_member_fn_begin_end_t : std::false_type {};
6969

7070
template <typename T>
71-
struct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()),
71+
struct has_member_fn_begin_end_t<T, void_t<decltype(*std::declval<T>().begin()),
7272
decltype(std::declval<T>().end())>>
7373
: std::true_type {};
7474

@@ -99,15 +99,15 @@ struct has_mutable_begin_end : std::false_type {};
9999

100100
template <typename T>
101101
struct has_const_begin_end<
102-
T,
103-
void_t<
104-
decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())),
105-
decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>
102+
T, void_t<decltype(*detail::range_begin(
103+
std::declval<const remove_cvref_t<T>&>())),
104+
decltype(detail::range_end(
105+
std::declval<const remove_cvref_t<T>&>()))>>
106106
: std::true_type {};
107107

108108
template <typename T>
109109
struct has_mutable_begin_end<
110-
T, void_t<decltype(detail::range_begin(std::declval<T&>())),
110+
T, void_t<decltype(*detail::range_begin(std::declval<T&>())),
111111
decltype(detail::range_end(std::declval<T&>())),
112112
// the extra int here is because older versions of MSVC don't
113113
// SFINAE properly unless there are distinct types

Diff for: test/ranges-test.cc

+6
Original file line numberDiff line numberDiff line change
@@ -742,3 +742,9 @@ TEST(ranges_test, movable_only_istream_iter_join) {
742742
EXPECT_EQ("1, 2, 3, 4, 5",
743743
fmt::format("{}", fmt::join(std::move(first), last, ", ")));
744744
}
745+
746+
struct not_range {
747+
void begin() const {}
748+
void end() const {}
749+
};
750+
static_assert(!fmt::is_formattable<not_range>{}, "");

0 commit comments

Comments
 (0)