Tải bản đầy đủ - 0 (trang)
Chapter 87.  Make predicates pure functions

# Chapter 87.  Make predicates pure functions

Tải bản đầy đủ - 0trang

Summary

Predicatepurity:Apredicateisafunctionobjectthatreturnsa

themathematicalsenseifitsresultdependsonlyonits

arguments(notethatthisuseof"pure"hasnothingtodowith

purevirtualfunctions).

Don'tallowpredicatestoholdoraccessstatethataffectsthe

resultoftheiroperator(),includingbothmemberandglobal

state.Prefertomakeoperator()aconstmemberfunctionfor

predicates(seeItem15).

Discussion

Algorithmsmakeanunknowablenumberofcopiesoftheir

predicatesatunknowabletimesinanunknowableorder,and

thengoontopassthosecopiesaroundwhilecasuallyassuming

thatthecopiesareallequivalent.

Thatiswhyit'syourresponsibilitytomakesurethatcopiesof

predicatesareindeedallequivalent,andthatmeansthatthey

mustbepurefunctions:functionswhoseresultisnotaffected

byanythingotherthantheargumentspassedtooperator().

evaluate.

Statefulpredicatesmayseemuseful,buttheyareexplicitlynot

veryusefulwiththeC++standardlibraryanditsalgorithms,

andthatisintentional.Inparticular,statefulpredicatescanonly

beusefulif:

Thepredicateisnotcopied:Thestandardalgorithmsmake

nosuchguarantee,andinfactassumethatpredicatesare

safelycopyable.

order:Thestandardalgorithmsgenerallymakeno

appliedtotheelementsintherange.Intheabsenceof

operationslike"flagthethirdelement"(seeExamples)

makelittlesense,becausewhichelementwillbevisited

"third"isnotwell-defined.

Itispossibletoworkaroundthefirstpointbywritinga

lightweightpredicatethatusesreference-countingtechniques

toshareitsdeepstate.Thatsolvesthepredicate-copying

problemtoobecausethepredicatecanbesafelycopiedwithout

changingitssemanticswhenitisappliedtoobjects.(See

[Sutter02].)Itisnotpossible,however,toworkaroundthe

secondpoint.

Alwaysdeclareapredicatetype'soperator()asaconst

memberfunctionsothatthecompilercanhelpyouavoidthis

mistakebyemittinganerrorifyoutrytochangeanydata

membersthatthepredicatetypemayhave.Thiswon'tprevent

allabusesforexample,itwon'tflagaccessestoglobaldatabutit

willhelpthecompilertohelpyouavoidatleastthemost

commonmistakes.

Examples

Example:FlagNth.Hereistheclassicexamplefrom[Sutter02],

whichisintendedtoremovethethirdelementfromacontainer

v:

classFlagNth{

public:

FlagNth(size_tn):current_(0),n_(n){}

//evaluatetotrueifandonlyifthisisthen-thinvocatio

template

booloperator()(constT&){return++current_==n_;}

private:

size_tcurrent_,n_;

};

//later

v.erase(remove_if(v.begin(),v.end(),FlagNth(3)));

Thisisnotguaranteedtoremovethethirdelement,even

thoughthatwasintended.Inmostreal-worldSTL

implementations,iterasesboththethirdandthesixth

elements.Why?Becauseremove_ifiscommonlyimplemented

intermsoffind_ifandremove_copy_if,anditpassesalonga

copyofthepredicatetoeachofthosefunctions,possiblyafterit

state.

Conceptually,thisexampleisperversebecauseremove_ifonly

guaranteesthatitwillremoveallelementssatisfyingsome

criterion.Itdoesnotdocumenttheorderinwhichelementsin

therangewillbevisitedorremoved,sothecodeisrelyingon

anassumed,butundocumentedandunsatisfied,assumption.

Thecorrectwaytoremoveaparticularelementistoiteratetoit

andthencallerase.

References

[Austern99]Đ4.2.2[Josuttis99]Đ5.8.2,Đ8.1.4[Meyers01]

Đ39[Stroustrup00]Đ10.2.6[Sutter02]Đ2-3

88.Preferfunctionobjectsover

functionsasalgorithmandcomparer

arguments

Summary

Discussion

References

Summary

Objectspluginbetterthanfunctions:Preferpassingfunction

objects,notfunctions,toalgorithms.Comparersforassociative

containersmustbefunctionobjects.Functionobjectsare