#include <iostream>
#include <inttypes.h>
#include <type_traits>
template <int F>
struct fp
{
enum { BITS = F };
int32_t s;
template<class B = int, typename std::enable_if<!std::is_same<B, int32_t>::value>::type...>
fp(const int & b) : s(((int32_t)b) << F) { }
fp(const int32_t & b) : s(b << F) { }
fp(const float & b) : s(b * (1 << F)) { }
template<int T>
fp(const fp<T> & b) { *this = b; }
template<class B = int, typename std::enable_if<!std::is_same<B, int32_t>::value>::type...>
fp & operator=(const int & b) { s = ((int32_t)b) << F; return *this; }
fp & operator=(const int32_t & b) { s = b << F; return *this; }
fp & operator=(const float & b) { s = b * (1 << F); return *this; }
fp & operator=(const fp & b) { s = b.s; return *this; }
template<int T>
fp & operator=(const fp<T> & b)
{
if (T > F) { s = b.s >> (T - F); }
else if (T < F) { s = b.s << (F - T); }
else { s = b.s; }
return *this;
}
/*fp & operator=(const int32_t & b)
{
s = b << F;
return *this;
}
fp & operator=(const float & b)
{
s = b * (1 << F);
return *this;
}*/
friend std::ostream & operator<<(std::ostream & os, const fp<F> & a) { os << a.s; return os; }
};
using fp824 = fp<24>;
using fp1616 = fp<16>;
using fp248 = fp<8>;
int main() {
// your code goes here
fp1616 a0(0); // error: ambiguous?!
fp1616 a1(1); // error: ambiguous?!
fp1616 a2(2); // error: ambiguous?!
fp1616 a3(-2.5f);
std::cout << a0 << std::endl;
std::cout << a1 << std::endl;
std::cout << a2 << std::endl;
std::cout << a3 << std::endl;
a0 = 5; // error: ambiguous?!
a0 = 0; // error: ambiguous?!
a0 = 3.4f;
fp824 b1(1.2f);
fp1616 b2(b1);
fp248 b3(b2);
b1 = b3;
b1 = b2;
return 0;
}