#include <iostream>
#include <limits>

template<typename Desired, typename Given>
constexpr Desired narrow_cast(Given arg) {
	static_assert(std::is_integral<Desired>::value, "Only integer types are supported");
	static_assert(std::is_integral<Given>::value, "Only integer types are supported");
	
	auto min = std::numeric_limits<Desired>::min();
	auto max = std::numeric_limits<Desired>::max();
	
	auto different_signs = std::is_signed<Given>::value xor std::is_signed<Desired>::value;
	if(sizeof(Desired) == sizeof(Given) && different_signs && arg < 0) {
		return 0;
	}
	
	return 
		min > arg? min:
		max < arg? max: 
		arg;
}

int main() {
	std::cout << narrow_cast<short>(100000) << std::endl;
	std::cout << narrow_cast<unsigned short>(100000) << std::endl;
	std::cout << narrow_cast<unsigned short>(-100000) << std::endl;
	std::cout << narrow_cast<int>(-1) << std::endl;
	std::cout << narrow_cast<unsigned int>(-1) << std::endl;
	std::cout << narrow_cast<unsigned short>(-1) << std::endl;
	return 0;
}