summaryrefslogtreecommitdiffhomepage
path: root/c++.html.markdown
diff options
context:
space:
mode:
authorDavid Hsieh <davidhsiehlo@gmail.com>2016-03-11 08:39:55 -0600
committerDavid Hsieh <davidhsiehlo@gmail.com>2016-03-11 08:39:55 -0600
commitceb99e14019672309ca80350054b7bb1a6642a48 (patch)
tree1cca5af13a146c0a36ef760b6264d18875290ec0 /c++.html.markdown
parent51c2f7ce28caf1cc654bcafc4063f3012cc2f0c3 (diff)
parent8d1e2e31ef9c62e2833ccb83cde78caef668f044 (diff)
Merge branch 'adambard-master' into r-spanish
Diffstat (limited to 'c++.html.markdown')
-rw-r--r--c++.html.markdown150
1 files changed, 134 insertions, 16 deletions
diff --git a/c++.html.markdown b/c++.html.markdown
index d03092e5..a02e7e5b 100644
--- a/c++.html.markdown
+++ b/c++.html.markdown
@@ -149,7 +149,7 @@ namespace First {
namespace Second {
void foo()
{
- printf("This is Second::foo\n")
+ printf("This is Second::foo\n");
}
}
@@ -330,7 +330,7 @@ ECarTypes GetPreferredCarType()
}
// As of C++11 there is an easy way to assign a type to the enum which can be
-// useful in serialization of data and converting enums back-and-forth between
+// useful in serialization of data and converting enums back-and-forth between
// the desired type and their respective constants
enum ECarTypes : uint8_t
{
@@ -352,7 +352,7 @@ void WritePreferredCarTypeToFile(ECarTypes InputCarType)
}
// On the other hand you may not want enums to be accidentally cast to an integer
-// type or to other enums so it is instead possible to create an enum class which
+// type or to other enums so it is instead possible to create an enum class which
// won't be implicitly converted
enum class ECarTypes : uint8_t
{
@@ -468,7 +468,7 @@ int main() {
// Inheritance:
// This class inherits everything public and protected from the Dog class
-// as well as private but may not directly access private members/methods
+// as well as private but may not directly access private members/methods
// without a public or protected method for doing so
class OwnedDog : public Dog {
@@ -801,6 +801,94 @@ void doSomethingWithAFile(const std::string& filename)
// all automatically destroy their contents when they fall out of scope.
// - Mutexes using lock_guard and unique_lock
+// containers with object keys of non-primitive values (custom classes) require
+// compare function in the object itself or as a function pointer. Primitives
+// have default comparators, but you can override it.
+class Foo {
+public:
+ int j;
+ Foo(int a) : j(a) {}
+};
+struct compareFunction {
+ bool operator()(const Foo& a, const Foo& b) const {
+ return a.j < b.j;
+ }
+};
+//this isn't allowed (although it can vary depending on compiler)
+//std::map<Foo, int> fooMap;
+std::map<Foo, int, compareFunction> fooMap;
+fooMap[Foo(1)] = 1;
+fooMap.find(Foo(1)); //true
+
+///////////////////////////////////////
+// Lambda Expressions (C++11 and above)
+///////////////////////////////////////
+
+// lambdas are a convenient way of defining an anonymous function
+// object right at the location where it is invoked or passed as
+// an argument to a function.
+
+// For example, consider sorting a vector of pairs using the second
+// value of the pair
+
+vector<pair<int, int> > tester;
+tester.push_back(make_pair(3, 6));
+tester.push_back(make_pair(1, 9));
+tester.push_back(make_pair(5, 0));
+
+// Pass a lambda expression as third argument to the sort function
+// sort is from the <algorithm> header
+
+sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs) {
+ return lhs.second < rhs.second;
+ });
+
+// Notice the syntax of the lambda expression,
+// [] in the lambda is used to "capture" variables
+// The "Capture List" defines what from the outside of the lambda should be available inside the function body and how.
+// It can be either:
+// 1. a value : [x]
+// 2. a reference : [&x]
+// 3. any variable currently in scope by reference [&]
+// 4. same as 3, but by value [=]
+// Example:
+
+vector<int> dog_ids;
+// number_of_dogs = 3;
+for(int i = 0; i < 3; i++) {
+ dog_ids.push_back(i);
+}
+
+int weight[3] = {30, 50, 10};
+
+// Say you want to sort dog_ids according to the dogs' weights
+// So dog_ids should in the end become: [2, 0, 1]
+
+// Here's where lambda expressions come in handy
+
+sort(dog_ids.begin(), dog_ids.end(), [&weight](const int &lhs, const int &rhs) {
+ return weight[lhs] < weight[rhs];
+ });
+// Note we captured "weight" by reference in the above example.
+// More on Lambdas in C++ : http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11
+
+///////////////////////////////
+// Range For (C++11 and above)
+///////////////////////////////
+
+// You can use a range for loop to iterate over a container
+int arr[] = {1, 10, 3};
+
+for(int elem: arr){
+ cout << elem << endl;
+}
+
+// You can use "auto" and not worry about the type of the elements of the container
+// For example:
+
+for(auto elem: arr) {
+ // Do something with each element of arr
+}
/////////////////////
// Fun stuff
@@ -852,20 +940,50 @@ Foo f1;
f1 = f2;
-// How to truly clear a container:
-class Foo { ... };
-vector<Foo> v;
-for (int i = 0; i < 10; ++i)
- v.push_back(Foo());
+///////////////////////////////////////
+// Tuples (C++11 and above)
+///////////////////////////////////////
+
+#include<tuple>
+
+// Conceptually, Tuples are similar to old data structures (C-like structs) but instead of having named data members ,
+// its elements are accessed by their order in the tuple.
+
+// We start with constructing a tuple.
+// Packing values into tuple
+auto first = make_tuple(10, 'A');
+const int maxN = 1e9;
+const int maxL = 15;
+auto second = make_tuple(maxN, maxL);
+
+// printing elements of 'first' tuple
+cout << get<0>(first) << " " << get<1>(first) << "\n"; //prints : 10 A
+
+// printing elements of 'second' tuple
+cout << get<0>(second) << " " << get<1>(second) << "\n"; // prints: 1000000000 15
+
+// Unpacking tuple into variables
+
+int first_int;
+char first_char;
+tie(first_int, first_char) = first;
+cout << first_int << " " << first_char << "\n"; // prints : 10 A
+
+// We can also create tuple like this.
+
+tuple<int, char, double> third(11, 'A', 3.14141);
+// tuple_size returns number of elements in a tuple (as a constexpr)
+
+cout << tuple_size<decltype(third)>::value << "\n"; // prints: 3
+
+// tuple_cat concatenates the elements of all the tuples in the same order.
-// Following line sets size of v to 0, but destructors don't get called
-// and resources aren't released!
-v.empty();
-v.push_back(Foo()); // New value is copied into the first Foo we inserted
+auto concatenated_tuple = tuple_cat(first, second, third);
+// concatenated_tuple becomes = (10, 'A', 1e9, 15, 11, 'A' ,3.14141)
-// Truly destroys all values in v. See section about temporary objects for
-// explanation of why this works.
-v.swap(vector<Foo>());
+cout << get<0>(concatenated_tuple) << "\n"; // prints: 10
+cout << get<3>(concatenated_tuple) << "\n"; // prints: 15
+cout << get<5>(concatenated_tuple) << "\n"; // prints: 'A'
```
Further Reading: