使用增强单元:是否可以为复合类型制定一个无量纲的转换
Using boost units: Is it possible to formulate a cast to dimensionless for composite types
我们希望将 boost::units 用于强类型,但也希望使用无量纲类型以实现兼容性,例如与其他图书馆。
有没有办法以通用方式实现它?
类似于以下代码的内容
(显然不能编译)
#include <boost/units/systems/si.hpp>
using namespace boost::units;
using SiTime = quantity<boost::units::si::time, double>;
using SiLength = quantity<boost::units::si::length, double>;
template<typename TIME,typename LENGTH>
struct Kernel{
using time_t = TIME;
using length_t = LENGTH;
};
using KernelD = Kernel<double,double>;
using KernelSi = Kernel<SiTime,SiLength>;
template<typename TO_KERNEL>
struct composite_cast{
template<template <typename> class COMPOSITE,typename FROM_KERNEL>
COMPOSITE<TO_KERNEL> operator()(COMPOSITE<FROM_KERNEL> value){
(void)value;
//how could this work ?
return COMPOSITE<TO_KERNEL>();
}
};
template<typename KERNEL>
struct Foo{
typename KERNEL::length_t length;
typename KERNEL::time_t time;
};
using FooSi = Foo<KernelSi>;
using FooD = Foo<KernelD>;
template<typename KERNEL>
struct Bar{
Foo<KERNEL> a;
Foo<KERNEL> b;
};
using BarSi = Bar<KernelSi>;
using BarD = Bar<KernelD>;
int main(int, char**) {
FooSi fooSi;
FooD fooD = composite_cast<KernelD>(fooSi);
BarSi barSi;
BarD barD = composite_cast<KernelD>(barSi);
return 0;
}
除了示例代码中的一连串语法错误外,此代码将无法运行,因为 COMPOSITE
需要是 template-template 参数类型 :
template <typename TO_KERNEL> struct composite_cast {
template <template <typename> class COMPOSITE, typename FROM_KERNEL>
COMPOSITE<TO_KERNEL> operator()(COMPOSITE<FROM_KERNEL> value) {
// how could this work ?
return {};
}
};
也就是说,我会在这里进行显式转换:
#include <boost/units/systems/si.hpp>
using namespace boost::units;
using SiTime = quantity<boost::units::si::time, double>;
using SiLength = quantity<boost::units::si::length, double>;
template <typename TIME, typename LENGTH> struct Kernel {
using time_t = TIME;
using length_t = LENGTH;
};
using KernelD = Kernel<double, double>;
using KernelSi = Kernel<SiTime, SiLength>;
template <typename KERNEL> struct Foo {
typename KERNEL::length_t length;
typename KERNEL::time_t time;
template <typename K2> explicit operator Foo<K2>() const { return {
quantity_cast<typename K2::length_t>(length),
quantity_cast<typename K2::time_t>(time) };
}
};
using FooSi = Foo<KernelSi>;
using FooD = Foo<KernelD>;
template <typename KERNEL> struct Bar {
Foo<KERNEL> a;
Foo<KERNEL> b;
template <typename K2> explicit operator Bar<K2>() const {
return { static_cast<Foo<K2>>(a), static_cast<Foo<K2>>(b) };
}
};
using BarSi = Bar<KernelSi>;
using BarD = Bar<KernelD>;
int main() {
FooSi fooSi;
FooD fooD = static_cast<FooD>(fooSi);
BarSi barSi;
BarD barD = static_cast<BarD>(barSi);
}
显式转换函数
如果您不想拥有会员运营商,请免费提供:
#include <boost/units/systems/si.hpp>
using namespace boost::units;
using SiTime = quantity<boost::units::si::time, double>;
using SiLength = quantity<boost::units::si::length, double>;
template <typename TIME, typename LENGTH> struct Kernel {
using time_t = TIME;
using length_t = LENGTH;
};
using KernelD = Kernel<double, double>;
using KernelSi = Kernel<SiTime, SiLength>;
template <typename KERNEL> struct Foo {
typename KERNEL::length_t length;
typename KERNEL::time_t time;
};
using FooSi = Foo<KernelSi>;
using FooD = Foo<KernelD>;
template <typename KERNEL> struct Bar {
Foo<KERNEL> a;
Foo<KERNEL> b;
};
template <typename K2, typename K1>
Foo<K2> kernel_cast(Foo<K1> const& foo) {
return {
quantity_cast<typename K2::length_t>(foo.length),
quantity_cast<typename K2::time_t>(foo.time)
};
}
template <typename K2, typename K1>
Bar<K2> kernel_cast(Bar<K1> const& bar) {
return { kernel_cast<K2>(bar.a), kernel_cast<K2>(bar.b) };
}
using BarSi = Bar<KernelSi>;
using BarD = Bar<KernelD>;
int main() {
FooSi fooSi;
FooD fooD = kernel_cast<KernelD>(fooSi);
BarSi barSi;
BarD barD = kernel_cast<KernelD>(barSi);
}
吃你的蛋糕也吃它
顺便说一下,free-function 方法与您原来的 composite_cast
函数对象非常吻合:
template <typename TO_KERNEL> struct composite_cast {
template <template <typename> class COMPOSITE, typename FROM_KERNEL>
COMPOSITE<TO_KERNEL> operator()(COMPOSITE<FROM_KERNEL> const& value) const {
return kernel_cast<TO_KERNEL>(value);
}
};
int main() {
composite_cast<KernelD> caster;
FooSi fooSi;
FooD fooD = caster(fooSi);
BarSi barSi;
BarD barD = caster(barSi);
}
我们希望将 boost::units 用于强类型,但也希望使用无量纲类型以实现兼容性,例如与其他图书馆。 有没有办法以通用方式实现它? 类似于以下代码的内容 (显然不能编译)
#include <boost/units/systems/si.hpp>
using namespace boost::units;
using SiTime = quantity<boost::units::si::time, double>;
using SiLength = quantity<boost::units::si::length, double>;
template<typename TIME,typename LENGTH>
struct Kernel{
using time_t = TIME;
using length_t = LENGTH;
};
using KernelD = Kernel<double,double>;
using KernelSi = Kernel<SiTime,SiLength>;
template<typename TO_KERNEL>
struct composite_cast{
template<template <typename> class COMPOSITE,typename FROM_KERNEL>
COMPOSITE<TO_KERNEL> operator()(COMPOSITE<FROM_KERNEL> value){
(void)value;
//how could this work ?
return COMPOSITE<TO_KERNEL>();
}
};
template<typename KERNEL>
struct Foo{
typename KERNEL::length_t length;
typename KERNEL::time_t time;
};
using FooSi = Foo<KernelSi>;
using FooD = Foo<KernelD>;
template<typename KERNEL>
struct Bar{
Foo<KERNEL> a;
Foo<KERNEL> b;
};
using BarSi = Bar<KernelSi>;
using BarD = Bar<KernelD>;
int main(int, char**) {
FooSi fooSi;
FooD fooD = composite_cast<KernelD>(fooSi);
BarSi barSi;
BarD barD = composite_cast<KernelD>(barSi);
return 0;
}
除了示例代码中的一连串语法错误外,此代码将无法运行,因为 COMPOSITE
需要是 template-template 参数类型 :
template <typename TO_KERNEL> struct composite_cast {
template <template <typename> class COMPOSITE, typename FROM_KERNEL>
COMPOSITE<TO_KERNEL> operator()(COMPOSITE<FROM_KERNEL> value) {
// how could this work ?
return {};
}
};
也就是说,我会在这里进行显式转换:
#include <boost/units/systems/si.hpp>
using namespace boost::units;
using SiTime = quantity<boost::units::si::time, double>;
using SiLength = quantity<boost::units::si::length, double>;
template <typename TIME, typename LENGTH> struct Kernel {
using time_t = TIME;
using length_t = LENGTH;
};
using KernelD = Kernel<double, double>;
using KernelSi = Kernel<SiTime, SiLength>;
template <typename KERNEL> struct Foo {
typename KERNEL::length_t length;
typename KERNEL::time_t time;
template <typename K2> explicit operator Foo<K2>() const { return {
quantity_cast<typename K2::length_t>(length),
quantity_cast<typename K2::time_t>(time) };
}
};
using FooSi = Foo<KernelSi>;
using FooD = Foo<KernelD>;
template <typename KERNEL> struct Bar {
Foo<KERNEL> a;
Foo<KERNEL> b;
template <typename K2> explicit operator Bar<K2>() const {
return { static_cast<Foo<K2>>(a), static_cast<Foo<K2>>(b) };
}
};
using BarSi = Bar<KernelSi>;
using BarD = Bar<KernelD>;
int main() {
FooSi fooSi;
FooD fooD = static_cast<FooD>(fooSi);
BarSi barSi;
BarD barD = static_cast<BarD>(barSi);
}
显式转换函数
如果您不想拥有会员运营商,请免费提供:
#include <boost/units/systems/si.hpp>
using namespace boost::units;
using SiTime = quantity<boost::units::si::time, double>;
using SiLength = quantity<boost::units::si::length, double>;
template <typename TIME, typename LENGTH> struct Kernel {
using time_t = TIME;
using length_t = LENGTH;
};
using KernelD = Kernel<double, double>;
using KernelSi = Kernel<SiTime, SiLength>;
template <typename KERNEL> struct Foo {
typename KERNEL::length_t length;
typename KERNEL::time_t time;
};
using FooSi = Foo<KernelSi>;
using FooD = Foo<KernelD>;
template <typename KERNEL> struct Bar {
Foo<KERNEL> a;
Foo<KERNEL> b;
};
template <typename K2, typename K1>
Foo<K2> kernel_cast(Foo<K1> const& foo) {
return {
quantity_cast<typename K2::length_t>(foo.length),
quantity_cast<typename K2::time_t>(foo.time)
};
}
template <typename K2, typename K1>
Bar<K2> kernel_cast(Bar<K1> const& bar) {
return { kernel_cast<K2>(bar.a), kernel_cast<K2>(bar.b) };
}
using BarSi = Bar<KernelSi>;
using BarD = Bar<KernelD>;
int main() {
FooSi fooSi;
FooD fooD = kernel_cast<KernelD>(fooSi);
BarSi barSi;
BarD barD = kernel_cast<KernelD>(barSi);
}
吃你的蛋糕也吃它
顺便说一下,free-function 方法与您原来的 composite_cast
函数对象非常吻合:
template <typename TO_KERNEL> struct composite_cast {
template <template <typename> class COMPOSITE, typename FROM_KERNEL>
COMPOSITE<TO_KERNEL> operator()(COMPOSITE<FROM_KERNEL> const& value) const {
return kernel_cast<TO_KERNEL>(value);
}
};
int main() {
composite_cast<KernelD> caster;
FooSi fooSi;
FooD fooD = caster(fooSi);
BarSi barSi;
BarD barD = caster(barSi);
}