#include <string>
#include <iostream>
#include <cstring>

int Max(int x, int y) {
    return x > y ? x : y;
}

std::string Max(std::string x, std::string y) {
    return x > y ? x : y;
}

/*
#include "max.h"

const char* Max(const char* x, const char* y);
*/

int main() {
    using namespace std;

    // (1) A function template defines a family of functions.

    cout << Max(3, 4) << ";" << Max( string{"abc"}, string{"xyz"} ) << endl;

    /*
    // (2) We can provide a non-template overload if
    //     the function template does not work for a particular type.

    cout << Max("AAA", "BBB") << endl;

    // (3) The compiler must see a template's whole definition in order to
    //     instantiate it with concrete types. Duplicate template instances
    //     in multiple object files will be resolved by the linker.

    int func1(int, int); // defined in func1.cpp; will instantiate Max(int,int)
    int func2(int, int); // defined in func2.cpp; will instantiate Max(int,int)

    cout << func1(5, 6) << ";" << func2(7, 8) << endl;
    */
}
