Movatterモバイル変換


[0]ホーム

URL:



This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofCD1 status.

561. inserter overly generic

Section: 24.5.2.4.3[inserter]Status:CD1Submitter: Howard HinnantOpened: 2006-02-21Last modified: 2016-01-28

Priority:Not Prioritized

View all issues withCD1 status.

Discussion:

The declaration ofstd::inserter is:

template <class Container, class Iterator>insert_iterator<Container>inserter(Container& x, Iterator i);

The template parameterIterator in this function is completely unrelatedto the template parameterContainer when it doesn't need to be. Thiscauses the code to be overly generic. That is, any type at all can be deducedasIterator, whether or not it makes sense. Now the same is true ofContainer. However, for every free (unconstrained) template parameterone has in a signature, the opportunity for a mistaken binding grows geometrically.

It would be much better ifinserter had the following signature instead:

template <class Container>insert_iterator<Container>inserter(Container& x, typename Container::iterator i);

Now there is only one free template parameter. And the second argument toinserter must be implicitly convertible to the container's iterator,else the call will not be a viable overload (allowing other functions in theoverload set to take precedence). Furthermore, the first parameter must have anested type namediterator, or again the binding tostd::inserteris not viable. Contrast this with the current situationwhere any type can bind toContainer orIterator and thosetypes need not be anything closely related to containers or iterators.

This can adversely impact well written code. Consider:

#include <iterator>#include <string>namespace my{template <class String>struct my_type {};struct my_container{template <class String>void push_back(const my_type<String>&);};template <class String>void inserter(const my_type<String>& m, my_container& c) {c.push_back(m);}}  // myint main(){    my::my_container c;    my::my_type<std::string> m;    inserter(m, c);}

Today this code fails because the call toinserter binds tostd::inserter instead of tomy::inserter. However with theproposed changestd::inserter will no longer be a viable function whichleaves onlymy::inserter in the overload resolution set. Everythingworks as the client intends.

To make matters a little more insidious, the above example works today if yousimply change the first argument to an rvalue:

    inserter(my::my_type(), c);

It will also work if instantiated with some string type other thanstd::string (or any otherstd type). It will also work if<iterator> happens to not get included.

And it will fail again for such inocuous reaons asmy_type ormy_container privately deriving from anystd type.

It seems unfortunate that such simple changes in the client's code can resultin such radically differing behavior.

Proposed resolution:

Change 24.2:

24.2 Header<iterator>synopsis

...template <class Container, class Iterator>   insert_iterator<Container> inserter(Container& x,Iteratortypename Container::iterator i);...

Change 24.4.2.5:

24.4.2.5 Class templateinsert_iterator

...template <class Container, class Iterator>   insert_iterator<Container> inserter(Container& x,Iteratortypename Container::iterator i);...

Change 24.4.2.6.5:

24.4.2.6.5inserter

template <class Container, class Inserter>   insert_iterator<Container> inserter(Container& x,Insertertypename Container::iterator i);

-1-Returns:insert_iterator<Container>(x,typename Container::iterator(i)).

[Kona (2007): This issue will probably be addressed as a part of the concepts overhaul of the library anyway, but the proposed resolution is correct in the absence of concepts. Proposed Disposition: Ready]


[8]ページ先頭

©2009-2026 Movatter.jp