// Example 7-7: Specializing a function template.
#include <cmath>

// primary template declaration
template<typename T> T root(T x, T y)
{
  return std::pow(x, 1.0/y);
}

// specialization where T is deduced to be long
template<> long root(long x, long y)
{
  if (y == 2)
    return std::sqrt((long double)x);
  else
    return std::pow((long double)x, 1.0l/y);
}

// specialization for explicit T=int
template<> int root<int>(int x, int y)
{
  if (y == 2)
    return std::sqrt(double(x));
  else
    return std::pow(double(x), 1.0/y);
}

// Overload with a different function template, such
// as valarray<T>.
template<template<typename> class C, typename T>
C<T> root(const C<T>& x, const C<T>& y)
{
  return std::pow(x, C<T>(1.0)/y);
}

int main()
{
  root(10, 2);
  root(10L, 2L);
  root(10.0, 2.0);
}
