// exceptions/exception-test.cpp - Test exceptions.
// 2004-02-10 - Fred Swartz

//==================================== includes
#include <iostream>
#include <stdexcept>
#include <string>
using namespace std;

//================================================ prototypes
void generateException(int whichException);

//====================================================== main
int main() {
    for (int i=1; ; i++) {  // Loop forever
	try {
	    cout << i;
	    generateException(i);
	} catch (out_of_range orex) {
	    cout << "    Catching: out_of_range "<< orex.what() << endl;
	} catch (const char* mess) {
	    cout << "    Catching: const char* " << mess << endl;
	} catch (string smess) {
	    cout << "    Catching: string " << smess << endl;
	} catch (int iex) {
	    cout << "    Catching: int " << iex << endl;
	} catch (runtime_error rex) {
	    cout << "    Catching: runtime_error " << rex.what() << endl;
	} catch (exception eex) {
	    cout << "    Catching: " << eex.what() << endl;
	} catch (...) {
	    cout << "    ERROR: Nobody caught this!" << endl;
	}
    }            

    return 0;
}

//========================================= generateException
void generateException(int whichException) {
    switch (whichException) {

	case 1:
	    cout << "  Throwing out_of_range()" << endl;
	    throw out_of_range("out_of_range meaningful comment");
	    break;

	case 2:
	    cout << "  Throwing exception()   // Can't specify comment" << endl;
	    throw exception();  // Doesn't take comment text.
	    break;

	case 3:
	    cout << "  Throwing underflow_error  // caught by base class (runtime_error)" << endl;
	    throw underflow_error("underflow_error");
	    break;

	case 4:
	    cout << "  Throwing runtime_error" << endl;
	    throw runtime_error("a comment");
	    break;

	case 5:
	    cout << "  Throwing length_error   // caught be super-super-class (exception)" << endl;
	    throw length_error("length_error");
	    break;

	case 6:
	    cout << "  Throwing int" << endl;
	    throw 26;
	    break;

	case 7:
	    cout << "  Throwing const char*" << endl;
	    throw "This is a const char*";
	    break;

	case 8:
	    cout << "  Throwing string" << endl;
	    throw string("I'm a string");
	    break;

	case 9:
	    cout << "  Throwing float" << endl;
	    throw 3.14159;
	    break;

	default:
	    cout << "  Throwing up" << endl;
	    exit(0);
    }
    return;

}
