#pragma once

#include <stdexcept>
#include <type_traits>

namespace StOpt
{

template<typename T, typename Enable = void>
struct PowInt
{
    static T eval(T x, int n)
    {
        if (n < 0)
            throw std::runtime_error("PowInt: negative exponent not supported");

        T res = T(1);

        while (n > 0)
        {
            if (n & 1)
                res *= x;

            x *= x;
            n >>= 1;
        }

        return res;
    }
};

template<typename T>
inline T powInt(const T& x, int n)
{
    return PowInt<std::decay_t<T>>::eval(x, n);
}

}
