#include <string>
#include <iostream>
 
// ----------------------------------------------
// Declaring typeclass interface, no implementation
// ----------------------------------------------
template <typename T>
class Show
{
public:
    static std::string show(T t);
};
 
// ----------------------------------------------
// Declare some instances via specification
// ----------------------------------------------
template <>
class Show<int>
{
public:
    static std::string show(int x)
    {
        return std::to_string(x); // yep, it's c++11
    }
};
 
template <>
class Show<std::string>
{
public:
    static std::string show(std::string s) { return s; }
};
 
// ----------------------------------------------
// Declaring function that use generic capabilities.
// Let's imagine that << is not overloaded...
// ----------------------------------------------
template <typename T>
void print(T obj)
{
    std::cout << Show<T>::show(obj) << std::endl;
}
 
// ----------------------------------------------
// testing
// ----------------------------------------------
int main()
{
    std::string message("Hi there");
 
    print(message);
    print(5);
    // print("Hello, world"); -- will not compile: no instance of Show
    return 0;
}