Защо boost препоръчва използването на основни функции вместо членски функции?

В документацията за увеличаване .geometry се посочва

Забележка: предпочитайте да използвате x = bg::get:‹0>(point1);
(за разлика от x = point1.get‹0>();)

Виждал съм това другаде в документите за усилване. Въпросът ми е защо? Това въпрос на най-добри практики ли е, производителност или някаква странност? Това общо правило ли е или специфично за тази библиотека?


person mmdanziger    schedule 21.01.2014    source източник
comment
За съществуващ тип точка (предоставен от някой друг), можете да приложите безплатна функция за получаване, която действа върху него, но не можете да добавите функция за получаване на член, така че е по-генерична.   -  person Marc Glisse    schedule 21.01.2014
comment
@MarcGlisse, но типът външна точка (ако е извлечен от базовия клас) няма ли задължително да има get така или иначе? Това ли е единствената причина?   -  person mmdanziger    schedule 21.01.2014
comment
Ако point1 има зависим тип, тогава също не е необходимо да пишете point1.template get<0>().   -  person Simple    schedule 21.01.2014


Отговори (1)


Това не е усилване само по себе си, а модерен C++ API дизайн.

  • Като не изисквате членски функции, можете да адаптирате вашите собствени класове и дори типове библиотеки на трети страни, за да работят с boost Api по ваш избор. (По този начин можете например да направите типове от библиотека на трета страна сериализируеми в архив на Boost Serialization).

  • Също така, като функциите са безплатни функции, има подобрено отделяне на зависимостите. Например: fusion/tuple.hpp не е необходимо да зависи от нищо, свързано с IO, тъй като операциите за поточно предаване са безплатни функции и следователно могат да бъдат декларирани (и дефинирани) в отделна заглавка: fusion/tuple_io.hpp.

  • Това също помага за капсулирането, защото по подразбиране безплатните функции не са friends на хост класа (и като такива не могат да имат достъп до частни членове).

  • безплатните функции могат да "направят правилното нещо" въз основа на ADL:

    using std::swap;
    swap(a, b); // will lookup `swap` in the namespaces that declare the parameter types
    

    (няколко други пространства от имена също се използват за търсене)

  • И накрая, безплатните функции могат генерично да обслужват група от типове, които не е необходимо да бъдат свързани с OO (свързани с наследяване). По този начин безплатните функции насърчават избягването на дублиране на код.

Редактиране Разглеждане на въпроса защо трябва да предпочетете синтаксиса, който не е член, ако и двата съществуват:

  • работи за типове, които нямат функция член
  • не изисква .template недвусмисленост в кода на шаблона (както е посочено от @Simple)
  • Отново: не е специфично за усилване.

    • c++03 has had std::swap() as a free function
    • c++11 въвежда std::begin() и std::end() като безплатни функции
    • std::hash<>, std::less<>, std::greater<>, std::equal_to<> по подобен начин предоставят точки за персонализиране, които не са натрапчиви (но не са функции разбира се)
person sehe    schedule 21.01.2014
comment
Извън темата: от интерес, какъв е случаят на използване за персонализиране на std::less с предпочитание пред безплатния operator<? Прав си, че предоставя точка за персонализиране, но мисля, че е доста неясна: искате вашият тип да бъде сравним по алгоритми и контейнери, но не и по код, който нормалните човешки същества пишат ;-) Има ли някаква досадна последица от частична специализация, което означава, че понякога трябва да се примирите с това? - person Steve Jessop; 21.01.2014
comment
@SteveJessop Най-досадното нещо при безплатните функции, за което се сещам, са клопките на ADL, т.е. че ADL може лесно да направи TheWrongThing(TM). Няма начин да се контролира ADL (освен да се забрани). Да, писателите на библиотеки могат (и трябва) да бъдат отбранителни по отношение на това (като използват ADL бариерни пространства от имена). Но функционалните обекти имат различното свойство, че не участват в ADL по дефиниция. (Знам, че Ерик Ниблер се е застъпил за това и го е използвал като принцип при проектирането на Proto0x). - person sehe; 21.01.2014
comment
Не знам дали това е принципът на проектиране на стандартната библиотека. Може би просто са искали способността напр. инстанцирайте типове контейнери с конкретен тип сравняване, за разлика от необходимостта винаги да инициализирате някакъв тип обща функция с конкретен обект на екземпляр при конструиране. - person sehe; 21.01.2014
comment
да, виждам причини std::less да съществува. Просто го използва като точка за персонализиране за дефиниран от потребителя тип, от което съм озадачен: позволено е, но не мисля, че някога съм го правил. - person Steve Jessop; 21.01.2014