#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace boost::type_erasure; namespace mpl = boost::mpl; namespace Inherited { class Socket { public: virtual void Connect() = 0; }; class TcpSocket : public Socket { public: virtual void Connect() { } }; } BOOST_TYPE_ERASURE_MEMBER((Erased)(HasConnect), Connect, 0) BOOST_TYPE_ERASURE_MEMBER((Erased)(HasDisconnect), Disconnect, 0) BOOST_TYPE_ERASURE_MEMBER((Erased)(HasBind), Bind, 0) namespace Erased { class TcpSocket { public: void Connect() { } void Disconnect() { } void Bind() { } }; typedef any, _self&> AnyConnect; // To test the cost of creating anys when the concept is more complex typedef any, HasDisconnect, HasBind >, _self&> AnySocket; } typedef any, _self&> AnyFunc; typedef any, copy_constructible<>>> AnyFunc2; timeval Now() { timeval result; gettimeofday(&result, NULL); return result; } double TimeDiff(timeval end, timeval begin) { int uDiff = end.tv_usec - begin.tv_usec; int sDiff = end.tv_sec - begin.tv_sec; return sDiff + uDiff / 1000000.0; } template void MeasureTime(const char* name, Action action) { int N = 100 * 1000 * 1000; sleep(1); // tries avoiding that the tests influence each other timeval begin = Now(); for (int i = 0; i < N; ++i) action(); timeval end = Now(); cout << name << ": " << TimeDiff(end, begin) << endl; } int main(int argc, char** argv) { cout << "* Classic inheritance replacement:" << endl; Inherited::TcpSocket iSock; Inherited::Socket& iSockRef = iSock; MeasureTime("Inherited", [&iSockRef] { iSockRef.Connect(); }); Erased::TcpSocket eSock; Erased::AnyConnect aSock(eSock); MeasureTime("Erased", [&aSock] { aSock.Connect(); }); MeasureTime("Erased + ctor", [&eSock] { Erased::AnyConnect ac(eSock); ac.Connect(); } ); MeasureTime("Erased + ctor 3 concepts", [&eSock] { Erased::AnySocket as(eSock); as.Connect(); } ); cout << endl; cout << "* boost::function replacement:" << endl; auto bindExpr = boost::bind(&Inherited::TcpSocket::Connect, iSock); MeasureTime("boost::bind", bindExpr); boost::function bf = bindExpr; MeasureTime("boost::function", bf); std::function stdf = std::bind(&Inherited::TcpSocket::Connect, iSock); MeasureTime("std::function", stdf); AnyFunc af1(bindExpr); MeasureTime("te::any + boost::bind", af1); AnyFunc2 af2([&iSock] { iSock.Connect(); }); MeasureTime("te::any + lambda", af2); return 0; }