Programming Language/C++

Templates, Exceptions, and Files

dr.meteor 2019. 11. 26. 00:30

1. Function Templates

파라미터의 타입을 한가지로 특정하고자 하지 않을 때 사용하며, 제네릭과 같은 개념

template <class T>
T sum(T a, T b) {
  return a+b;
}

int main () {
    int x=7, y=15;
    cout << sum(x, y) << endl;
}

// Outputs 22

When creating a template type parameter, the keyword typename may be used as an alternative to the keyword class: template <typename T>. In this context, the keywords are identical, but throughout this course, we'll use the keyword class.

T is short for Type, and is a widely used name for type parameters.
It's not necessary to use T, however; you can declare your type parameters using any identifiers that work for you. The only terms you need to avoid are C++ keywords. Remember that when you declare a template parameter, you absolutely must use it in your function definition. Otherwise, the compiler will complain!

 

 

2. Class Templates

template <class T>
class Pair {
 private:
  T first, second;
 public:
  Pair (T a, T b):
   first(a), second(b) {
  }
};

A specific syntax is required in case you define your member functions outside of your class - for example in a separate source file. For example, to have a member function bigger() defined outside of the class, the following syntax is used:

template <class T>
class Pair {
 private:
  T first, second;
 public:
  Pair (T a, T b):
   first(a), second(b){
  }
  T bigger();
};

template <class T>
T Pair<T>::bigger() {
  // some code
}

To create objects of the template class for different types, specify the data type in angle brackets, as we did when defining the function outside of the class.

Pair <int> obj(11, 22);
cout << obj.bigger();
// Outputs 22

Pair <double> obj(23.43, 5.68);
cout << obj.bigger();
// Outputs 23.43

 

 

3. Template Specialization

In case of regular class templates, the way the class handles different data types is the same; the same code runs for all data types. Template specialization allows for the definition of a different implementation of a template when a specific type is passed as a template argument. For example, we might need to handle the character data type in a different manner than we do numeric data types. To demonstrate how this works, we can first create a regular template.

template <class T>
class MyClass {
 public:
  MyClass (T x) {
   cout <<x<<" -  not a char"<<endl;
  }
};
// As a regular class template, MyClass treats all of the various data types in the same way.

To specify different behavior for the data type char, we would create a template specialization.

template <class T>
class MyClass {
 public:
  MyClass (T x) {
   cout <<x<<" -  not a char"<<endl;
  }
};

template < >
class MyClass<char> {
 public:
  MyClass (char x) {
   cout <<x<<" is a char!"<<endl;
  }
};

In the example above, the first class is the generic template, while the second is the specialization. If necessary, your specialization can indicate a completely different behavior from the behavior of the generic template.

Keep in mind that there is no member "inheritance" from the generic template to the specialization, so all members of the template class specializations must be defined on their own.

 

 

4. Exceptions

In the throw statement, the operand determines a type for the exception. This can be any expression. The type of the expression's result will determine the type of the exception thrown.

try {
  int motherAge = 29;
  int sonAge = 36;
  if (sonAge > motherAge) {
   throw 99;
  }
} 
catch (int x) {
  cout<<"Wrong age values - Error "<<x;
}

//Outputs "Wrong age values - Error 99"

The try block throws the exception, and the catch block then handles it. The error code 99, which is an integer, appears in the throw statement, so it results in an exception of type int.

 

아래 코드는 순서에 유의하며 공부

int main() {
  int num1;
  cout <<"Enter the first number:";
  cin >> num1;

  int num2;
  cout <<"Enter the second number:";
  cin >> num2;

  if(num2 == 0) {
   throw 0;
  } 

  cout <<"Result:"<<num1 / num2;  

 catch(int x) {
  cout <<"Division by zero!";
 }
}

In our case, we catch exceptions of type integer only. It's possible to specify that your catch block handles any type of exception thrown in a try block. To accomplish this, add an ellipsis (...) between the parentheses of catch:

try {
  // code
} catch(...) {
  // code to handle exceptions
}

 

 

5. Working with Files
Another useful C++ feature is the ability to read and write to files. That requires the standard C++ library called fstream.
Three new data types are defined in fstream:
ofstream: Output file stream that creates and writes information to files.
ifstream: Input file stream that reads information from files.
fstream: General file stream, with both ofstream and ifstream capabilities that allow it to create, read, and write information to files.

To perform file processing in C++, header files <iostream> and <fstream> must be included in the C++ source file.

#include <iostream>
#include <fstream>
using namespace std;

int main() {
  ofstream MyFile;
  MyFile.open("test.txt");

  MyFile << "Some text! \n";
  MyFile.close();
}

You can also provide the path to your file using the ofstream objects constructor, instead of calling the open function.

#include <fstream>
using namespace std;

int main() {
  ofstream MyFile("test.txt");

  MyFile << "This is awesome! \n";
  MyFile.close();
}

Under certain circumstances, such as when you don't have file permissions, the open function can fail. The is_open() member function checks whether the file is open and ready to be accessed.

#include <iostream>
#include <fstream>
using namespace std;

int main() {
  ofstream MyFile("test.txt");

  if (MyFile.is_open()) {
   MyFile << "This is awesome! \n";
  }
  else {
   cout << "Something went wrong";
  }
  MyFile.close();
}

 

An optional second parameter of the open function defines the mode in which the file is opened. This list shows the supported modes.


All these flags can be combined using the bitwise operator OR (|). For example, to open a file in write mode and truncate it, in case it already exists, use the following syntax:

ofstream outfile;
outfile.open("file.dat", ios::out | ios::trunc );

 

The getline function reads characters from an input stream and places them into a string.

#include <iostream>
#include <fstream>
using namespace std;

int main () {
  string line;
  ifstream MyFile("test.txt");
  while ( getline (MyFile, line) ) {
   cout << line << '\n';
  }
  MyFile.close();
}


The example above reads a text file and prints the contents to the screen.
Our while loop uses the getline function to read the file line by line.