struct Reader{ void ReadMessage( const boost::tuple<int, const char*, const char*>& );};...Reader r;// --- шаблономагия проанализует тип параметра метода// и поймет какие тупли может принимать данный подписчикSubscribe(r, &Reader::ReadMessage);// --- сгенерирует тупель boost::tuple<int, const char*, const char*>// и доставит всем, кто подписался на негоSendMessage(10)("hello")("world")();...
SendMessage(10)(true)();...void Reader::ReadMessage( const boost::tuple<int,bool>& ) { ... }
SendMessage(10, true);...void Reader::ReadMessage( const int&, const bool& ) { ... }
#include <iostream>#include <memory>struct value{ value(const int v1, const int v2) :v1(v1),v2(v2) {} // --- назовите причины, почему был использован именно шаблон // а не просто std::ostream какой нибудь? template<class T>friend ::std::basic_ostream<T>& operator<<(::std::basic_ostream<T>& os, const value& obj ) { return os << "value = {"<< obj.v1 << ", " << obj.v2 << "};"; } int v1,v2;};struct base{ // --- нет виртуального диструктора // такая ситуация трактуется стандартом языка // как UB. // в случае одиночного наследования // провоцирует утечки памяти // (вызова диструктора наследника по указателю на базовый класс не происходит) // в случае с множественным наследованием // программа крашется в рантайме на всех топовых компиляторах: // (cl/gcc/clang) virtual void foo()const = 0;};struct der: base{ // --- тем не менее все равно будет вызван диструктор потомка ~der() { std::cout<<"der: dtor\n"; } der(const int v1, const int v2) :v(v1,v2) {} virtual void foo()const { std::cout << v << '\n'; } value v;};int main(){ std::cout << "Hello, world!\n"; // --- тип смарт-поинтера параметризуется // базовым классом // у которого нет виртуального диструктора const std::shared_ptr<base> shared = std::make_shared<der>(10,20); shared->foo(); // класс std::shared_ptr<base> // оперирует указателем на базовый класс base // и ничего не знает о его возможных наследниках // тем не менее, когда время жизни объекта закончится // он позавет правильный диструктор потомка // каким образом он догадыватся, какой нужен диструктор // и как вообще он умыдряется его запускать?}
// класс std::shared_ptr<base> // оперирует указателем на базовый класс base // и ничего не знает о его возможных наследниках // тем не менее, когда время жизни объекта закончится // он позавет правильный диструктор потомка // каким образом он догадыватся, какой нужен диструктор // и как вообще он умыдряется его запускать?}
// --- назовите причины, почему был использован именно шаблон // а не просто std::ostream какой нибудь? template<class T>friend ::std::basic_ostream<T>& operator<<(::std::basic_ostream<T>& os, const value& obj )