使用 boost-unit 获取给定数量的基本单元的功率
Get power of base unit of a given quantity with boost-unit
我想知道 boost-unit
是否可以用在我的一个项目中。对于大部分功能我都非常满意。但是我真的无法自己制作一个功能。
特别是,我正在寻找一个易于使用的函数,它可以为我提供给定数量的某个基本单元的功率。它在某种程度上与 pow 函数相反。实际上,io.hpp
实现了类似的东西,但我既不想复制粘贴所有内容,也不想深入研究此模板代码。
下面描述的 getPow
函数是否有简单的解决方法?
#include <boost/units/systems/si.hpp>
#include <boost/units/io.hpp>
#include <iostream>
using namespace boost::units;
template<typename U, typename V>
int getPow(quantity<U>& q, V) {
int ret = 0;
// What do I have to write here?
return ret;
}
int main(int argc, char** args) {
auto q = 1.*si::meter*si::meter/si::second;
std::cout << q << std::endl;
std::cout << getPow(q, si::meter) << std::endl; // Should output 2
std::cout << getPow(q, si::second) << std::endl; // Should output -1
}
下面的代码实现了你所需要的。我以前没有用过boost::units,所以可能有更惯用的方法来解决这个问题。
#include <type_traits>
#include <iostream>
#include <boost/mpl/at.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/io.hpp>
using namespace boost::units;
template <typename T>
using get_dimension_t = typename T::unit_type::dimension_type;
template<typename T>
struct get_tag
{
using type = typename T::tag_type;
};
template <typename T>
using get_tag_t = typename T::tag_type;
template< class ... > using void_t = void;
template<typename U, typename V>
struct Exponent
{
template <typename Dim, typename Enable = void>
struct get
{
static constexpr int value = 0;
};
template <typename Dim>
struct get<Dim, void_t<typename Dim::value_type>>
{
using Value = typename Dim::value_type;
static constexpr int value = Value::Numerator / Value::Denominator;
};
using dimension_V = get_dimension_t<V>;
using tag_to_search_for = typename get_tag<typename boost::mpl::at_c<dimension_V, 0>::type>::type;
using dimension_U = get_dimension_t<U>;
using iter = typename boost::mpl::find_if<dimension_U, std::is_same<get_tag<boost::mpl::_1>, tag_to_search_for> >::type;
using Dim = typename boost::mpl::deref<iter>::type;
constexpr static int value = get<Dim>::value;
};
template <typename U, typename V>
constexpr auto getExponent(U&& u, V&& v)
{
return Exponent<std::decay_t<U>, std::decay_t<V>>::value;
}
int main(int argc, char** args) {
auto q = 1.*si::meter*si::meter/si::second;
std::cout << q << std::endl;
std::cout << getExponent(q, si::meter) << std::endl; // Should output 2
std::cout << getExponent(q, si::second) << std::endl; // Should output -1
auto r = 1.*si::radian;
std::cout << getExponent(r, si::meter) << std::endl; // Should output 0
}
我想知道 boost-unit
是否可以用在我的一个项目中。对于大部分功能我都非常满意。但是我真的无法自己制作一个功能。
特别是,我正在寻找一个易于使用的函数,它可以为我提供给定数量的某个基本单元的功率。它在某种程度上与 pow 函数相反。实际上,io.hpp
实现了类似的东西,但我既不想复制粘贴所有内容,也不想深入研究此模板代码。
下面描述的 getPow
函数是否有简单的解决方法?
#include <boost/units/systems/si.hpp>
#include <boost/units/io.hpp>
#include <iostream>
using namespace boost::units;
template<typename U, typename V>
int getPow(quantity<U>& q, V) {
int ret = 0;
// What do I have to write here?
return ret;
}
int main(int argc, char** args) {
auto q = 1.*si::meter*si::meter/si::second;
std::cout << q << std::endl;
std::cout << getPow(q, si::meter) << std::endl; // Should output 2
std::cout << getPow(q, si::second) << std::endl; // Should output -1
}
下面的代码实现了你所需要的。我以前没有用过boost::units,所以可能有更惯用的方法来解决这个问题。
#include <type_traits>
#include <iostream>
#include <boost/mpl/at.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/io.hpp>
using namespace boost::units;
template <typename T>
using get_dimension_t = typename T::unit_type::dimension_type;
template<typename T>
struct get_tag
{
using type = typename T::tag_type;
};
template <typename T>
using get_tag_t = typename T::tag_type;
template< class ... > using void_t = void;
template<typename U, typename V>
struct Exponent
{
template <typename Dim, typename Enable = void>
struct get
{
static constexpr int value = 0;
};
template <typename Dim>
struct get<Dim, void_t<typename Dim::value_type>>
{
using Value = typename Dim::value_type;
static constexpr int value = Value::Numerator / Value::Denominator;
};
using dimension_V = get_dimension_t<V>;
using tag_to_search_for = typename get_tag<typename boost::mpl::at_c<dimension_V, 0>::type>::type;
using dimension_U = get_dimension_t<U>;
using iter = typename boost::mpl::find_if<dimension_U, std::is_same<get_tag<boost::mpl::_1>, tag_to_search_for> >::type;
using Dim = typename boost::mpl::deref<iter>::type;
constexpr static int value = get<Dim>::value;
};
template <typename U, typename V>
constexpr auto getExponent(U&& u, V&& v)
{
return Exponent<std::decay_t<U>, std::decay_t<V>>::value;
}
int main(int argc, char** args) {
auto q = 1.*si::meter*si::meter/si::second;
std::cout << q << std::endl;
std::cout << getExponent(q, si::meter) << std::endl; // Should output 2
std::cout << getExponent(q, si::second) << std::endl; // Should output -1
auto r = 1.*si::radian;
std::cout << getExponent(r, si::meter) << std::endl; // Should output 0
}