mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-30 18:57:34 +02:00
Protect against overloaded comma operators in decltype
This commit is contained in:
committed by
Victor Zverovich
parent
467520e7a4
commit
430e6ac9b6
@ -56,8 +56,8 @@ template <typename Char> struct test_stream : std::basic_ostream<Char> {
|
|||||||
template <typename T, typename Char> class is_streamable {
|
template <typename T, typename Char> class is_streamable {
|
||||||
private:
|
private:
|
||||||
template <typename U>
|
template <typename U>
|
||||||
static decltype(internal::declval<test_stream<Char>&>()
|
static decltype((void)(internal::declval<test_stream<Char>&>()
|
||||||
<< internal::declval<U>(),
|
<< internal::declval<U>()),
|
||||||
std::true_type())
|
std::true_type())
|
||||||
test(int);
|
test(int);
|
||||||
|
|
||||||
|
@ -537,14 +537,15 @@ struct parts_container_concept_check : std::true_type {
|
|||||||
|
|
||||||
template <typename T> static std::false_type has_add_check(check_second);
|
template <typename T> static std::false_type has_add_check(check_second);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static decltype(declval<T>().add(declval<typename T::format_part_type>()),
|
static decltype((void)declval<T>().add(
|
||||||
|
declval<typename T::format_part_type>()),
|
||||||
std::true_type()) has_add_check(check_first);
|
std::true_type()) has_add_check(check_first);
|
||||||
typedef decltype(has_add_check<PartsContainer>(check_first())) has_add;
|
typedef decltype(has_add_check<PartsContainer>(check_first())) has_add;
|
||||||
static_assert(has_add::value, "PartsContainer doesn't provide add() method");
|
static_assert(has_add::value, "PartsContainer doesn't provide add() method");
|
||||||
|
|
||||||
template <typename T> static std::false_type has_last_check(check_second);
|
template <typename T> static std::false_type has_last_check(check_second);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static decltype(declval<T>().last(),
|
static decltype((void)declval<T>().last(),
|
||||||
std::true_type()) has_last_check(check_first);
|
std::true_type()) has_last_check(check_first);
|
||||||
typedef decltype(has_last_check<PartsContainer>(check_first())) has_last;
|
typedef decltype(has_last_check<PartsContainer>(check_first())) has_last;
|
||||||
static_assert(has_last::value,
|
static_assert(has_last::value,
|
||||||
@ -554,7 +555,8 @@ struct parts_container_concept_check : std::true_type {
|
|||||||
static std::false_type has_substitute_last_check(check_second);
|
static std::false_type has_substitute_last_check(check_second);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static decltype(
|
static decltype(
|
||||||
declval<T>().substitute_last(declval<typename T::format_part_type>()),
|
(void)declval<T>().substitute_last(
|
||||||
|
declval<typename T::format_part_type>()),
|
||||||
std::true_type()) has_substitute_last_check(check_first);
|
std::true_type()) has_substitute_last_check(check_first);
|
||||||
typedef decltype(has_substitute_last_check<PartsContainer>(
|
typedef decltype(has_substitute_last_check<PartsContainer>(
|
||||||
check_first())) has_substitute_last;
|
check_first())) has_substitute_last;
|
||||||
@ -563,7 +565,7 @@ struct parts_container_concept_check : std::true_type {
|
|||||||
|
|
||||||
template <typename T> static std::false_type has_begin_check(check_second);
|
template <typename T> static std::false_type has_begin_check(check_second);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static decltype(declval<T>().begin(),
|
static decltype((void)declval<T>().begin(),
|
||||||
std::true_type()) has_begin_check(check_first);
|
std::true_type()) has_begin_check(check_first);
|
||||||
typedef decltype(has_begin_check<PartsContainer>(check_first())) has_begin;
|
typedef decltype(has_begin_check<PartsContainer>(check_first())) has_begin;
|
||||||
static_assert(has_begin::value,
|
static_assert(has_begin::value,
|
||||||
@ -571,7 +573,7 @@ struct parts_container_concept_check : std::true_type {
|
|||||||
|
|
||||||
template <typename T> static std::false_type has_end_check(check_second);
|
template <typename T> static std::false_type has_end_check(check_second);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static decltype(declval<T>().end(),
|
static decltype((void)declval<T>().end(),
|
||||||
std::true_type()) has_end_check(check_first);
|
std::true_type()) has_end_check(check_first);
|
||||||
typedef decltype(has_end_check<PartsContainer>(check_first())) has_end;
|
typedef decltype(has_end_check<PartsContainer>(check_first())) has_end;
|
||||||
static_assert(has_end::value, "PartsContainer doesn't provide end() method");
|
static_assert(has_end::value, "PartsContainer doesn't provide end() method");
|
||||||
|
@ -76,7 +76,7 @@ template <typename OutputIterator> void copy(char ch, OutputIterator out) {
|
|||||||
template <typename T> class is_like_std_string {
|
template <typename T> class is_like_std_string {
|
||||||
template <typename U>
|
template <typename U>
|
||||||
static auto check(U* p)
|
static auto check(U* p)
|
||||||
-> decltype(p->find('a'), p->length(), p->data(), int());
|
-> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
|
||||||
template <typename> static void check(...);
|
template <typename> static void check(...);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -106,7 +106,8 @@ template <typename T> class is_tuple_like_ {
|
|||||||
template <typename U>
|
template <typename U>
|
||||||
static auto check(U* p)
|
static auto check(U* p)
|
||||||
-> decltype(std::tuple_size<U>::value,
|
-> decltype(std::tuple_size<U>::value,
|
||||||
internal::declval<typename std::tuple_element<0, U>::type>(),
|
(void)internal::declval<
|
||||||
|
typename std::tuple_element<0, U>::type>(),
|
||||||
int());
|
int());
|
||||||
template <typename> static void check(...);
|
template <typename> static void check(...);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user