在 C++11 中,如何实现适合内置类型层次结构的算术类型?
In C++11, how can I implement an arithmetic type that fits into the hierarchy of builtin types?
基本上,我想实现一个 float16
类型。但是这个问题不是关于如何做到这一点的细节,而是关于如何进行设置,以便我的新 float16 类型能够适当地处理 float、double 和所有整数类型。
我希望我的 float16
类型能够类似地转换为 float 或 double。例如,它应该隐式转换为这两种类型。它也应该有 std::common_type (http://en.cppreference.com/w/cpp/types/common_type) 的行为类似于它的 std::common_types 对其他浮点类型的行为。这意味着 std::common_type<my_float16, float>::type = float
、std::common_type<my_float16, double>::type = double
和 std::common_type<my_float16, T>::type = my_float16
,其中 T
是任何整数类型。
我需要编写哪些构造函数和强制转换运算符才能完成这项工作?如有任何帮助,我们将不胜感激!
我的 可能是相关的。
编辑:好的,我像 Anton 那样构建了一个最小的例子。这是
struct float16 {
explicit operator int() {
return 0;
}
operator float() {
return 0.0f;
}
};
这对float和float16的公共类型是正确的,但是int和float16的公共类型仍然是int。我不明白。
我不认为你能准确理解这一点,因为 C++ 核心语言对待本地定义的转换(例如 char
到 int
)不同于用户定义的转换(即使它们是隐式的) ).
例如
之后
struct float16 { float16(int) {} }; // cast int->float16 is implicit
struct Foo { Foo(const double&){} }; // constructor accepts a double&
struct Bar { Bar(const float16&){} }; // constructor accepts a float16&
void foo(const Foo&) {}
void bar(const Bar&) {}
调用 foo(3)
是有效的,因为整数 3
可以隐式转换为 double
并且 foo
接受 Foo
实例通过用户定义的转换(不是 explicit
的 Foo
构造函数)从 double
隐式构造。
但是 bar(3)
无效 因为这样的调用需要两次隐式用户定义转换(int
→float16
和 float16
→Bar
),这是不允许的。
如果将其实现为 struct/class 类型,请提供所有相关运算符和构造函数的重载。如果 class 支持与其他类型之间的转换,请查阅指南了解它需要什么。
如果您希望 class 与 std::common_type
和 std::numeric_limits
等标准模板完美搭配,您需要为这些模板提供适当的专业化。最好阅读实际标准以了解此类专业化要求的描述,但可能有一些教程 material(我已经看到很好的介绍性 material 专业化 std::numeric_limits
,但是不适用于 std::common_type
).
除非您使用特定于编译器的类型,否则您的类型如何适应内置标准类型(int
、float
等)总是会有一些限制。
我将对这个问题提供我自己的答案。
我现在同意 6502,我认为这不可能以简单的方式实现。我发现这样做的唯一方法是为每种可能的类型组合提供运算符重载。这可以使用模板(和 Boost 运算符 http://www.boost.org/doc/libs/1_59_0/libs/utility/operators.htm 是一个很好的例子)以稍微好一点的方式完成,但这仍然是大量的工作和样板代码。
基本上,我想实现一个 float16
类型。但是这个问题不是关于如何做到这一点的细节,而是关于如何进行设置,以便我的新 float16 类型能够适当地处理 float、double 和所有整数类型。
我希望我的 float16
类型能够类似地转换为 float 或 double。例如,它应该隐式转换为这两种类型。它也应该有 std::common_type (http://en.cppreference.com/w/cpp/types/common_type) 的行为类似于它的 std::common_types 对其他浮点类型的行为。这意味着 std::common_type<my_float16, float>::type = float
、std::common_type<my_float16, double>::type = double
和 std::common_type<my_float16, T>::type = my_float16
,其中 T
是任何整数类型。
我需要编写哪些构造函数和强制转换运算符才能完成这项工作?如有任何帮助,我们将不胜感激!
我的
编辑:好的,我像 Anton 那样构建了一个最小的例子。这是
struct float16 {
explicit operator int() {
return 0;
}
operator float() {
return 0.0f;
}
};
这对float和float16的公共类型是正确的,但是int和float16的公共类型仍然是int。我不明白。
我不认为你能准确理解这一点,因为 C++ 核心语言对待本地定义的转换(例如 char
到 int
)不同于用户定义的转换(即使它们是隐式的) ).
例如
之后struct float16 { float16(int) {} }; // cast int->float16 is implicit
struct Foo { Foo(const double&){} }; // constructor accepts a double&
struct Bar { Bar(const float16&){} }; // constructor accepts a float16&
void foo(const Foo&) {}
void bar(const Bar&) {}
调用 foo(3)
是有效的,因为整数 3
可以隐式转换为 double
并且 foo
接受 Foo
实例通过用户定义的转换(不是 explicit
的 Foo
构造函数)从 double
隐式构造。
但是 bar(3)
无效 因为这样的调用需要两次隐式用户定义转换(int
→float16
和 float16
→Bar
),这是不允许的。
如果将其实现为 struct/class 类型,请提供所有相关运算符和构造函数的重载。如果 class 支持与其他类型之间的转换,请查阅指南了解它需要什么。
如果您希望 class 与 std::common_type
和 std::numeric_limits
等标准模板完美搭配,您需要为这些模板提供适当的专业化。最好阅读实际标准以了解此类专业化要求的描述,但可能有一些教程 material(我已经看到很好的介绍性 material 专业化 std::numeric_limits
,但是不适用于 std::common_type
).
除非您使用特定于编译器的类型,否则您的类型如何适应内置标准类型(int
、float
等)总是会有一些限制。
我将对这个问题提供我自己的答案。
我现在同意 6502,我认为这不可能以简单的方式实现。我发现这样做的唯一方法是为每种可能的类型组合提供运算符重载。这可以使用模板(和 Boost 运算符 http://www.boost.org/doc/libs/1_59_0/libs/utility/operators.htm 是一个很好的例子)以稍微好一点的方式完成,但这仍然是大量的工作和样板代码。