How does one generally get the end of a string in C++0x?
template<typename ForwardIterator, typename StringType>
inline bool starts_with(ForwardIterator begin, ForwardIterator end, const StringType& target)
{
assert(begin < end);
if (std::distanc开发者_如何学运维e(std::begin(target), std::end(target)) > std::distance(begin, end))
{
return false;
}
return std::equal(std::begin(target), std::end(target), begin);
}
This fails because std::end
returns one past the '\0'
if StringType
is a string literal, not the '\0'
. (In this respect, it's similar to the range based for loop inconsistency ) How does one work around this?
How about making a little trait class for your string template parameter:
template <typename TString>
struct StringBounds
{
typedef typename TString::const_iterator citerator;
static citerator Begin(const TString & s) const { return std::begin(s); }
static citerator End (const TString & s) const { return std::end(s); }
};
template <typename TChar, size_t N>
struct StringBounds<TChar[N]>
{
typedef const TChar * citerator;
static citerator Begin(const TChar(&s)[N]) const { return s; }
static citerator End (const TChar(&s)[N]) const { return s + N - 1; }
};
Usage:
std::equal(StringBounds<StringType>::Begin(target), StringBounds<StringType>::End(target), begin)
Pass a proper std::string
instead.
String literals don't have their own "type"; your input data could be considered to be mangled, essentially.
You could specialise/overload for char const*
, which almost universally will be null-terminated.
Your API is a template API. Use template specialization to create specialized versions for char*
and actual iterator types.
Also, there is a reason why the C++ standard algorithms deal only in iterators and not containers (like StringType
).
精彩评论