Наткнулся я там на очень интересное (интересно для меня в первую очередь, потому что я его не знал, хотя думаю опытные программисты C++ в курсе его) правило. Это тема 25 в этой книге, называется "Поиск, зависимый от типов аргументов". Еще это называется Argument Dependent Lookup, или ADL. Для интереса решил составить небольшую задачку на это правило и спросить, тех C++ разработчиков (в основном с небольшим опытом разработки), кто был онлайн - никто правильно не ответил.
Смысл заключается в следующем: компилятор при поиске имени функции (для её вызова) будет проверять и пространства имён, в которых находятся аргументы этой функции. Сразу же приведу пример, чтобы было понятно.
#include <iostream> namespace mynamespace { struct someStruct { void write() const { std::cout << "Some Text" << std::endl; } }; void foo( someStruct& obj ) { obj.write(); } } int main( int argc, char* argv[] ) { mynamespace::someStruct obj; foo( obj ); return 0; }Поидее правильнее было писать:
mynamespace::foo( obj );т.к. функция foo находится в области видимости mynamespace. Но согласно правилу выше, компилятор при поиске имени функции для её вызова будет проверять и пространства имен, содержащие типы аргументов вызова функции, а у нас аргумент ссылка на объект someStruct& из области видимости mynamespace. Поэтому для foo можно не писать mynamespace::. Какие проблемы это может вызвать эта "фича" языка C++? Вот приведу пример, который задавал вчера всем:
#include <iostream> namespace mynamespace { class X { public: void getText() const { std::cout << "someText" << std::endl; } }; void foo( X* obj ) { std::cout << "ololo" << std::endl; obj->getText(); } } void foo( mynamespace::X* obj ) { obj->getText(); } int main( int argc, char* argv[] ) { mynamespace::X obj; foo( &obj ); return 0; }Что произойдёт с этим кодом? Ниодин человек не сказал, что он не просто не скомпилится (из-за двусмысленности, я впрочем тоже бы наверное не догадался бы). Компилятор напишет следующее (gcc ):
igor@igor-desktop:~/cpp_test$ g++ -Wall namespace_test.cpp -o namespace_test namespace_test.cpp: In function ‘int main(int, char**)’: namespace_test.cpp:24: error: call of overloaded ‘foo(mynamespace::X*)’ is ambiguous namespace_test.cpp:18: note: candidates are: void foo(mynamespace::X*) namespace_test.cpp:11: note: void mynamespace::foo(mynamespace::X*)
А всё почему? У нас есть глобальная функция foo, но аргумент у неё из mynamespace - mynamespace::X*, соответственно по правилу ADL поиск функции будет происходить и в mynamespace, а там есть своя функция foo. Поэтому будет двусмысленность для компилятора и он просто не даст скомпилировать.
Вот такое интересное правило, а может просто фича языка C++. Я думаю опытные программисты с ним знакомы, а начинающим будет полезно узнать.