如何编写生成基元类型的模板
How to write a template resulting in a primitive type?
我正在编写一个小的不动点算术类,其中包含整数和小数位数的模板参数。当乘以两个小的不动点类型时,结果应该是一个更大的不定点类型,以获取完整的结果。例如,将两个8.8的固定点号相乘,得到16.16的固定点数。
我的课是这样的:
template<typename T, unsigned int bits, unsigned int frac>
class FixedPoint {
public:
constexpr FixedPoint(int x = 0) : raw_(x << frac) { }
constexpr FixedPoint(double x) : raw_(x * (T(1) << frac)) { }
private:
T raw_;
}
现在的问题是T模板参数,尤其是对于乘法,因为结果类型与参数类型不同,无法推断。写入a*b无效。
我想做的是用模板类型Int<bits+frac>是一个int8_t、int16_t、int 32_t或int 64_t,具体取决于所需的总位数。
我该怎么写这样的字体?我可以把它限制在8、16、32或64位。
您可以使用模板和专业化:
template <std::size_t N> struct sizedType;
template <> struct sizedType<8> { using type = std::uint8_t; };
template <> struct sizedType<16> { using type = std::uint16_t; };
template <> struct sizedType<32> { using type = std::uint32_t; };
template <> struct sizedType<64> { using type = std::uint64_t; };
最简单(因此也是最好的)是使用别名
template<std::size_t bits>
using integer_with_bits =
conditional_t<(bits<= 8), std::int8_t,
conditional_t<(bits<=16), std::int16_t,
conditional_t<(bits<=32), std::int32_t,
enable_if_t <(bits<=64), std::int64_t> > > >;
这是相当于运行时CCD_ 1级联的编译时间。那么integer_with_bits<3>
就是int8_t
,而integer_with_bits<65>
(以及更大的值)会产生编译时错误。在上面我使用了辅助
template<bool C, typename T>
using enable_if_t = typename std::enable_if<C,T>::type;
template<bool C, typename T1, typename T2>
using conditional_t = typename std::conditional<C,T1,T2>::type;
这并没有将其限制为所需的位。相反,它找到了适合这么多比特的最小的:
template<class T>struct tag{using type=T;};
template<size_t bits_at_least>
struct int_helper : int_helper<bits_at_least+1> {};
template<> struct int_helper<8 > : tag<int8_t > {};
template<> struct int_helper<16 > : tag<int16_t> {};
template<> struct int_helper<32 > : tag<int32_t> {};
template<> struct int_helper<64 > : tag<int64_t> {};
template<> struct int_helper<128> {}; // unsupported
template<std::size_t bits>
using integer = typename int_helper<bits>::type;
则CCD_ 5为CCD_。
integer<65>
到integer<128>
是一个SFINAE错误(漂亮而干净),而integer<129>
是一个会向您发送垃圾邮件的错误(因为它试图实例化递归模板的无限级联)。
我们可以通过删除多达63个递归实例化并进行比特篡改来加快编译速度并生成更好的错误。
template<size_t n>
using size = std::integral_constant<std::size_t, n>;
template<size_t n>
struct bits : size<bits<n/2>{}+1 > {};
template<>
struct bits<0> : size<0> {};
template<class T>struct tag{using type=T;};
template<size_t bits_of_bits>
struct int_helper_2 {};
// optional 0 bits of bits uses char:
template<> struct int_helper_2<0> : tag<int8_t > {};
template<> struct int_helper_2<1> : tag<int8_t > {};
template<> struct int_helper_2<2> : tag<int8_t > {};
template<> struct int_helper_2<3> : tag<int8_t > {};
template<> struct int_helper_2<4> : tag<int16_t> {};
template<> struct int_helper_2<5> : tag<int32_t> {};
template<> struct int_helper_2<6> : tag<int64_t> {};
template<size_t bits_needed>
struct int_helper : int_helper_2< bits<bits_needed>{} > {};
template<size_t bits_needed>
using integer<bits_needed>=typename int_helper<bits_needed>::type;
这在所有大小下都会产生不错的SFINAE错误,并且编译速度应该更快(更少的类型递归)。
相关文章:
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- 有没有办法避免为 std::variant 类成员中的所有类型编写构造函数?
- C++:是否可以编写一个函数,将不同类型的元素附加到变体数组中?
- 避免使用 std::any 编写相同的重复类型检查代码
- 在 C++ 中编写一个程序,要求用户输入 C++ 中所有基元类型的值
- 为模板类中的特定类型编写比较器函数
- 如何编写模板函数来添加整数但连接字符串和字符类型?
- 如何编写使用迭代器和特定类型的模板化函数
- 有没有优雅的方法可以在多态 lambda 中编写类型别名
- 编写完整专业化以识别void类型的问题
- 编写一个函数,该函数将通过判断其每个参数的类型来自动确定其返回值
- C++/Eigen:获取为 MatrixBase 编写的模板的矩阵参数类型
- 如何编写模板以转换为基于整数/枚举的模板化类型
- 如何在不取消定义类型的情况下为 C++ 中的类型编写 getter?
- 如何编写指定模板化基的类型参数的派生类
- 如何为数据类型 vector<glm::vec3> (opengl 数据类型) 编写 std::minmax 函数的自定义比较器
- 如何编写操作员==与隐式铸造/构造类型一起使用
- 在编写特征以进行参考和非参考类型时,如何减少重复
- 是否有可能在c++中为向量(或其他类似的数据类型)编写用户迭代类
- 在模板类之外的容器类型上编写模板化的成员函数