简体   繁体   中英

Why doesn't basic_string::append (iter, iter) call std::copy?

I just figured out that in Visual Studio C++ 2010, basic_string::append (iter, iter) is, obviously, not implemented by making use of std::copy .

First question:

Now suppose I implement my own iterator type, together with an optimized overloading of std::copy for my iterator type in order to provide more efficient block-wise copying. Is there any way to get basic_string::append to make use of this optimization, apart from overloading append as well?

Is there any chance that basic_string::append (iter, iter) does not do character-wise copying?

Second question (as a starting point for my own implementation):

Is the following guaranteed to be valid?

std::string t ("JohnB");
std::string s;
s.reserve (10);
std::copy (t.begin (), t.end (), s.begin ());
s.push_back ('\0');

or should I better use a back_inserter ? If I use a back_inserter -- how can I avoid character-wise copying?

The string class has its own traits class that defines the operations it can do on the characters it contains.

To copy char s, basic_string<char> will use std::char_traits<char>::copy (instead of the more general std::copy ). That probably maps to the memcpy function in the standard C library.

The definition of std::basic_string<cT, ...>::append() keeps delegating a few time before it eventually arrives at the overload (21.4.6.2 [string::append] paragraph 7):

basic_string& append(const charT* s, size_type n);

At this point there is clearly none of the original iterators left. In case you wonder what happens to the input iterator you may have passed to append() , the got removed by the overload in paragraph 17 of the same paragraph which states:

Effects: Equivalent to append(basic_string(first, last)) .

at some intermediate state. If the standard library is implemented the way as it is literally stated by the standard there is clearly no call to std::copy() .

You wouldn't really be able to see your overloaded version of std::copy() anyway, though. What the library may do is the moral equivalent of

template <typename InIt>
std::basic_string<cT, ...>& std::basic_string<cT, ...>::append(InIt begin, InIt end) {
    if (is_forward_iterator<begin>::value) {
        this->reserve(this->size() + std::distance(begin, end));
    }
    std::copy(begin, end, back_inserter_without_capacity_check<InIt>(*this);
}

Now, the other interesting bit is: Even if this is how it implemented, it doesn't really help you with respect to std::copy() ! You cannot partially specialize std::copy() (well, you can't partially specialize any function template) and the type of target iterator is not defined (in the above implementation it would be a non-capacity checking variant of std::back_inserter() if InIt is a forward iterator and otherwise it would just be the same as std::back_inserter() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM