4. 01. using namespace std::chrono; // see §35.2
02. auto t0 = high_resolution_clock::now();
03. do_work();
04. auto t1 = high_resolution_clock::now();
05. cout << duration_cast<milliseconds>(t1–t0).count() << "msecn";
5. 01. // smallest positive float (§40.2)
02. constexpr float min = numeric_limits<float>::min();
03.
04. // the number of bytes in an int
05. constexpr int szi = sizeof(int);
6. 01. // for random-access iterators we can subscript into [beg:end)
02. template<typename Ran>
03. void sort_helper(Ran beg, Ran end, random_access_iterator_tag)
04. {
05. sort(beg,end); // just sort it
06. }
01. // for forward iterators we can traverse [beg:end)
02. template<typename For>
03. void sort_helper(For beg, For end, forward_iterator_tag)
04. {
05. // initialize a vector from [beg:end)
06. vector<decltype(*beg)> v {beg,end};
07. sort(v.begin(),v.end());
08. // copy the elements back
09. copy(v.begin(),v.end(),beg);
10. }
7. 01. template<typname C>
02. void sort(C& c)
03. {
04. using Iter = Iterator_type<C>;
05. sort_helper(c.begin(),c.end(),Iterator_category<Iter>{});
06. }
8. 01. // yes, int is an arithmetic type
02. bool b1 = Is_arithmetic<int>();
03.
04. // no, std::string is not an arithmetic type
05. bool b2 = Is_arithmetic<string>();
01. template<typename Scalar>
02. class complex {
03. Scalar re, im;
04. public:
05. static_assert(Is_arithmetic<Scalar>()
06. , "Sorry, I only support complex of arithmetic types");
07. // ...
08. };
9. 01. void f(vector<string>& v)
02. {
03. // pp is a pair<vector<string>::iterator,int>
04. auto pp = make_pair(v.begin(),2);
05. // ...
06. }
01. // the type is explicitly specified
02. tuple<string,int,double> t2("Sild",123, 3.14);
03.
04. // the type is deduced t is a tuple<string,int,double>
05. auto t = make_tuple(string("Herring"),10, 1.23);
06.
07. string s = get<0>(t); // get first element of tuple
08. int x = get<1>(t);
09. double d = get<2>(t);
Editor's Notes
علاوه بر containerها و امکانات I/O کتابخونه استاندارد یه سری امکانات مفید دیگه هم داره.
Clock و duration برای اندازه گیری زمان و محاسبات زمان
Type function ها مثل iterator_traits و is_arithmetic و غیره که برای بدست آوردن اطلاعات در مورد typeها استفاده میشه و توی meta programming کاربرد داره
Pair و tuple هم برای نگه داری typeهای heterogeneous یا غیر همگون استفاده میشن.
این utilityها برای ساختن کتابخونه های دیگه مورد استفاده قرار گرفتن و خود کتابخونه استاندارد هم از اونا استفاده می کنه.
یکی از امکانات کتابخونه استاندارد برای ما time هست که یه سری عملیات های پایه ای رو برای ما فراهم کرده.
توابع clock یه time_point یا یه نقطه در زمان رو بر می گردونن. اگه 2 تا time_point رو از هم کم کنید یه duration یا یک دوره زمانی حاصلش میشه. واحد های زمانی هم مثل nanoseconds و Milliseconds هم تعرف شدن و می تونیم duration رو با duration_cast به این واحد های زمانی تبدیل کنیم.
برای استفاده از امکانات time باید هدر فایل chrono رو include کنیم و تمامی امکانات اون در فضای نام chrono که در داخل std قرار داره.
توی این مثال می تونیم زمان انجام شدن تابع do_work رو محاسبه کنیم و ببینیم که چقدر طول میکشه که انجام بشه.
یه سری امکانات در اختیار داریم که می تونیم با استفاده از اونا یه type رو بگیریم و در زمان کامپایل اطلاعاتی رو از اونا بدست بیاریم. ای این امکانات برای نوشتن کتابخونه های خودمون می تونیم استفاده کنیم و یا اینکه با استفاده از اونا برنامه های general بنویسیم و در meta programming به ما کمک می کنن. مثلا numeric_limits که در هدر فایل limits قرار داره یکی از اوناست.
مثلا با استفاده از تابع min میتونیم کوچکترین عدد مثبتی که میتونیم توی float ذخیره کنیم رو بدست بیاریم.
زمانی که ما از تابع sort استفاده می کنیم باید 2 تا iterator بهش بدیم که ابتدا و انتهای یه sequence از المانها باشن. این iteratorها باید به صورت random access باشن تا بتونیم مرتبشون کنیم. مثلا forward_list این قابلیت رو نداره و نمیشه با iterator های اون به عقب برگشت. یه container مثل forwar_list فقط Iteratorهایی از نوع forward iterator رو پشتیبانی می کنه.
حالا باید چطور این مشکل رو حل کرد؟ می تونیم 2 تا تابع کمکی بنویسیم. 2 تا ورودی اون Iterator های اول و آخر containerهستند و یه ورودی اضافه هم به نام random_access_iterator_tag داره که برای تشخیص اینکه Iteratorها random access هستند یا نه استفاده می شه. ورژنی که Iterator هایی از نوع random access میگیره خیلی ساده عملیات sort رو انجام میده.
ورژنی که forward iterator میگیره هم به همون سادگی ابتدا کل لیست رو توی وکتور کپی می کنه و بعد عملیات sort رو روی وکتور انجام میده و حاصل رو دوباره توی لیست کپی می کنه.
کلمه ی decltype یه تابعی مثل sizeof هست که کارش اینه که type آرگمانش رو برگردونه. از decltype برای ساختن یه وکتور با type درست استفاده می کنیم.
حالا باید یه عملیات خیلی جالب و محیر العقول انجام بدیم که بتونیم از اون دوتا helper function که تو اسلاید قبل نوشتیم استفاده کنیم. این کار رو با 2 تا type به نام های Iterator_type که یه container رو میگیره و iterator اون رو بر میگردونه و همینطور Iterator_category که یه tag یا برچسب میسازه که نوع Iterator رو مشخص می کنه انجام میدیم. و بقیه کارها رو کامپایلر با توجه به type ورودی تابع sort_helper انجام میده و تابع مناسب رو call میکنه. نکته خیلی هیجان انگیز اینه که تمام این کارها در زمان کامپایل انجام میشه. به این تکنیک tag dispatch میگیم که در کتابخونه استاندارد به وفور از این تکنیک استفاده شده. برای استفاده از این تکنیک شما باید هدر فایل iterator رو به برنامه include کنید.
Type predicateها زمانی استفاده میشن که ما می خوایم یه اطلاعاتی در مورد typeها بدست بیاریم. مثلا اگه بخوایم بدونیم که یه type از نوع arithmetic یا ریاضیاتی هست از is_arithmetic استفاده می کنیم. مثلا برای int جواب true هست چون با type ی int میشه عملیات ریاضی انجام داد ولی با string نمیشه. برای استفاده از این قابلیت ها باید هدر فایل type_traits رو include کنید. این فایل امکانات خیلی زیادی در اختیار برنامه میذاره.
از این قابلیت ها می شه برای concept checking توی template meta programming استفاده کرد. به عنوان مثال برای کلاس complex ما می تونیم با is_arithmetic چک کنیم که typeیی که به عنوان scaler داده میشه حتما از نوعی باشه که عملیات ریاضی بشه باهاش انجام داد. برای چک کردن از قابلیت static_assert که از c++11 اضافه شده استفاده می کنیم. Static_assert یه چیزی مثل assert معمولیه ولی زمان کامپایل شرطش چک میشه. در صورتی که شرط درست باشه هیچ اتفاقی نمیوفته ولی زمانی که شرط غلط باشه باعث compile error میشه.
گاهی اوقات نیاز داریم که فقط یه سری دیتا رو نگه داریم مثلا یه مجموعه value رو می خوایم ذخیره کنیم. می تونیم یه struct تعریف کنیم و برای هر کدوم از اون valueها یه اسم بذاریم. یه راه دیگه هم اینه که از tuple یا pair استفاده کنیم. بعضی از توابع کتابخونه استاندارد به عنوان خروجی pair برمیگردونن مثلا equal_range یه pair برمیگردونه. به اولین عضو pair، first میگیم و دومین عضوش رو second میگیم. برای استفاده از pair باید هدر فایل utility رو include کرد. تابع make_pair برای ما یه Pair میسازه و بر میگردونه.
اگر نیاز باشه که بیش تر از 2 تا المان رو نگه داریم از tuple استفاده می کنیم. Tuple یه Sequence از یه سری المان heterogeneous یا غیرهمگون هستش. غیرهمگون یعنی مثل آرایه نیست که تمام المان ها از یک type باشن.
المان های tuple از صفر شماره گذاری شدن. بخاطر اینکه درtuple عناصر نامگذاری نشدن. برای دسترسی به عناصر باید از تابع get استفاده کنیم و شماره عنصری که میخوایم به این صورت بنویسیم. از pair برای بعضی return typeبعضی از interfaceهای کتابخونه استاندارد استفاده شده چون ممکنه بخواد چندتا مقدار رو به عنوان خروجی برگردونه. اما اینکه نیاز باشه بیش از 2 تا خروجی داشته باشیم خیلی کم اتفاق میفته و از tuple بیشتر برای generic programming استفاده میشه.
این ویدیو آخرین ویدیوی آموزش سی پلاس پلاسه و یه جمع بندی از این دوره آموزش ها بکنیم. ما در این سری آموزش ها، part 1 کتاب the c++ programming language نوشته ی آقای استرواستراپ رو توی 18 تا ویدیو ارائه دادیم. Part 1 کتاب فقط به صورت introduction هست و زیاد وارد جزئیات نمیشه و شامل 5 تا فصله.
فصل یک یه سری نکاتی در مورد نحوی خوندن کتاب هست.
فصل دوم در مورد basic های زبانه.
فصل سوم در مورد مکانیزم ها abstraction هست
فصل چهارم در مورد کتابخونه استاندارد شامل containerها و الگوریتم هاست
و فصل پنجم در مورد concurrency هست.
کتاب شامل 3 تا part دیگه هم میشه و در کل 44 تا فصل داره و از فصل 6 به بعد به طور کامل زبان سی پلاس پلاس رو با جزئیات توضیح داده. اگه علاقه مند بودید می تونید مطالعه کنید.