По историческим причинам стандартная библиотека обычно использует size_t
, которая является неподписанным номером, в качестве результата типа функций размера. Исключением является std::count
. Но std::string::size()
является одним из size_t
функций,
Поскольку язык гарантирует модульную арифметику для выражения без знака типа, вы получите наматывается вокруг, где -1
становится наибольшее значение без знака типа.
Другой и IMO более очевидно глупо следствием является то, что
std::string("Hello").size() < -1
является гарантировано. Просто чистая бессмыслица, как текст исходного кода, когда можно вспомнить, что целью исходного кода высокого уровня является более четкое общение с людьми.
Чтобы избежать этой путаницы можно определить логическую подписанную Size
типа в качестве псевдонима для ptrdiff_t
(который является знаковым типом аналог size_t
) и поддакивать функции размера static_size
, n_items
и length
, плюс клетчатой is_empty
, как следующим образом:
sizes_and_lengths.hpp
#pragma once
// p/cppx/core_language_support/sizes_and_lengths.hpp
// Copyright © Alf P. Steinbach 2015. Boost Software License 1.0.
#include <p/cppx/core_language_support/basic_types.hpp>
#include <p/cppx/core_language_support/overloading.hpp> // cppx::(Object_argument etc.)
#include <p/cppx/core_language_support/type_builders.hpp> // cppx::(Ptr_, Ref_, Array_of_, ...)
#include <p/cppx/core_language_support/tmp/If_.hpp> // cppx::(If_, Is_)
#include <p/cppx/core_language_support/tmp/type_relationships.hpp> // cppx::Is_convertible_to_
#include <string> // std::basic_string
#include <utility> // std::declval
namespace progrock{ namespace cppx{
// These templates use size_t to accommodate g++, which has bug in this area.
// static_size()
// Static capacity of a collection.
template< class Type, size_t n >
constexpr
auto static_size(In_ref_<Raw_array_of_<n, Type>>)
-> Size
{ return n; }
template< class Type, size_t n >
constexpr
auto static_size(In_ref_<Array_of_<n, Type>>)
-> Size
{ return n; }
template< size_t n >
constexpr
auto static_size(In_ref_<std::bitset<n>>)
-> Size
{ return n; }
// n_items() & is_empty()
// Right-typed (signed integer) dynamic size of a collection.
template< class Type >
auto n_items(In_ref_<Type> o)
-> Size
{ return o.size(); }
template< size_t n >
auto n_items(In_ref_<std::bitset<n>> o)
-> Size
{ return o.count(); } // Corresponds to std::set<int>::size()
namespace impl {
using std::declval;
template< class Type >
constexpr
auto has_std_empty_checker(...)
-> bool
{ return false; }
template< class Type >
constexpr
auto has_std_empty_checker(int)
-> If_<
Is_<bool, decltype(declval<const Type>().empty())>, // CFINAE
Then_<bool> // SFINAE
>
{ return true; }
struct Using_empty_method
{
template< class Type >
auto is_empty(In_ref_<Type> o) const
-> bool
{ return o.empty(); }
};
struct Using_n_items_function
{
template< class Type >
auto is_empty(In_ref_<Type> o) const
-> bool
{ return (n_items(o) == 0); }
};
} // namespace impl
template< class Type >
constexpr
auto has_std_empty_checker()
-> bool
{ return impl::has_std_empty_checker<Type>(42); }
template< class Type >
auto is_empty(In_ref_<Type> o)
-> bool
{
using Impl = Ifc_<
has_std_empty_checker<Type>(),
Then_<impl::Using_empty_method>,
Else_<impl::Using_n_items_function>
>;
return Impl().is_empty(o);
}
template< size_t n >
auto is_empty(In_ref_<std::bitset<n>> bits)
-> bool
{ return bits.none(); }
// length() & length_of_literal() & is_empty
// Lengths of strings.
template< class Char, size_t n >
constexpr
auto length_of_literal(In_ref_<Raw_array_of_<n, Char>>) // "length" wraps this.
-> Size
{ return n - 1; }
template< class Type >
auto length(Object_argument, In_ref_<Type> s)
-> Size
{ return s.length(); }
template< class Char
, class Enabled_ = If_< Is_in_< Character_types, Char > >
>
auto length(Pointer_argument, In_value_<Ptr_<const Char>> s)
-> Size
{
auto p = s;
while(*p != 0) { ++p; }
return p - s;
}
template< class Char, size_t n
, class Enabled_ = If_< Is_in_< Character_types, Char > >
>
auto constexpr length(Array_argument, In_ref_<Raw_array_of_<n, Char>> a)
-> Size
{ return length_of_literal(a); }
template< class Type >
auto length(In_ref_<Type> o)
-> Size
{ return length(Arg_kind_<Type>(), o); }
template< class Char
, class Enabled_ = If_< Is_in_< Character_types, Char > >
>
auto is_empty(In_value_<Ptr_<const Char>> s)
-> bool
{ return (*s == 0); }
}} // namespace progrock::cppx
Если вы хотите использовать этот код, частично или в целом, реж Кроме того, не принося вспомогательные файлы из cppx library, вам придется перевести, например. In_
- тип, который вы предпочитаете для логического аргумента и т. Д. Библиотека cppx - это очень важная вещь, но ее можно использовать как есть. Он предоставляет такие вещи, как вышесказанное, те самые основы, которые каким-то образом пропустили стать частью стандартной библиотеки или даже были предложены.
Посмотрите на тип возвращаемого типа 'string :: size'. – ZDF
@ZDF спасибо! Я знаю, что допустил ошибку. – jianhui
Почему бы прямо не сравнить два значения, которые вы хотите сравнить? 'if (haystack.size()
e0k