浮动模板专业化
Template specialization for float
我知道,我不能在模板中使用 float 作为非类型参数。所以我想用一个分子和一个分母来表示我的极限 class.
我的限制 class 获取类型以及最小值和最大值。要对 int 和 float 使用 Limit,我目前使用这个:
template <typename U, typename T = U, T A1 = 0, T A2 = 0, T A3 = 0, T A4 = 0>
struct Limit {
static constexpr const U min = A1;
static constexpr const U max = A2;
};
template <intmax_t A1, intmax_t A2, intmax_t A3, intmax_t A4>
struct Limit<float, intmax_t, A1, A2, A3, A4> {
static constexpr const float min = A1 / (float) A2;
static constexpr const float max = A3 / (float) A4;
};
Limit<float, intmax_t, 40, 20, 30, 40> a;
Limit<int, 10, 20> b;
有什么方法可以优化这个实现吗?也许为浮动实现启用默认值?
提前致谢!
编辑:我想要一个像这样的模板声明(不工作):
// For int, char, short, uint32_t etc...
template <typename U, U MIN, U MAX>
struct Limit {
static constexpr const U min = MIN;
static constexpr const U max = MAX;
};
// For float/double
template <typename T /*float or double*/, typename MIN, typename MAX>
struct Limit {
static constexpr const T min = MIN.num / (T) MIN.dem; // static cast...
static constexpr const T max = MAX.num / (T) MAX.dem; // static cast...
};
Limit<int, int, 10, 20> a;
Limit<float, std::ratio<4,5>, std::ratio<10,15>> b;
我认为您的实施非常适合使用 std::ratio
。您可以为 min
和 max
使用两个原始 std::ratio
或如下所示的一些实现:
template<typename U, std::intmax_t NumerMin = 0, std::intmax_t DenomMin = 1,
std::intmax_t NumerMax = 0, std::intmax_t DenomMax = 1>
struct Limit {
static const std::ratio<NumerMin, DenomMin> min_;
static const std::ratio<NumerMax, DenomMax> max_;
public:
U const min = static_cast<U>(min_.num) / static_cast<U>(min_.den);
U const max = static_cast<U>(max_.num) / static_cast<U>(max_.den);
};
您可以始终将其包装在 ratio
中,这样您就可以编写 Limit<int, std:::ratio<100>, std::ratio<200>>
...
或者你可以按照
的方式做一些事情
// if T is floating point, return std::intmax_t, otherwise T.
template<class T>
using adjust_floating = std::conditional_t<std::is_floating_point<T>{}, std::intmax_t, T>;
template <class T, adjust_floating<T> A1 = 0,
adjust_floating<T> A2 = 0,
adjust_floating<T> A3 = 0,
adjust_floating<T> A4 = 0 >
struct Limit {
// maybe static_assert that A3 and A4 are zero if T isn't floating point
static constexpr T min = std::is_floating_point<T>{} ? A1 / (T) A2 : A1;
static constexpr T max = std::is_floating_point<T>{} ? A3 / (T) A4 : A2;
};
我知道,我不能在模板中使用 float 作为非类型参数。所以我想用一个分子和一个分母来表示我的极限 class.
我的限制 class 获取类型以及最小值和最大值。要对 int 和 float 使用 Limit,我目前使用这个:
template <typename U, typename T = U, T A1 = 0, T A2 = 0, T A3 = 0, T A4 = 0>
struct Limit {
static constexpr const U min = A1;
static constexpr const U max = A2;
};
template <intmax_t A1, intmax_t A2, intmax_t A3, intmax_t A4>
struct Limit<float, intmax_t, A1, A2, A3, A4> {
static constexpr const float min = A1 / (float) A2;
static constexpr const float max = A3 / (float) A4;
};
Limit<float, intmax_t, 40, 20, 30, 40> a;
Limit<int, 10, 20> b;
有什么方法可以优化这个实现吗?也许为浮动实现启用默认值?
提前致谢!
编辑:我想要一个像这样的模板声明(不工作):
// For int, char, short, uint32_t etc...
template <typename U, U MIN, U MAX>
struct Limit {
static constexpr const U min = MIN;
static constexpr const U max = MAX;
};
// For float/double
template <typename T /*float or double*/, typename MIN, typename MAX>
struct Limit {
static constexpr const T min = MIN.num / (T) MIN.dem; // static cast...
static constexpr const T max = MAX.num / (T) MAX.dem; // static cast...
};
Limit<int, int, 10, 20> a;
Limit<float, std::ratio<4,5>, std::ratio<10,15>> b;
我认为您的实施非常适合使用 std::ratio
。您可以为 min
和 max
使用两个原始 std::ratio
或如下所示的一些实现:
template<typename U, std::intmax_t NumerMin = 0, std::intmax_t DenomMin = 1,
std::intmax_t NumerMax = 0, std::intmax_t DenomMax = 1>
struct Limit {
static const std::ratio<NumerMin, DenomMin> min_;
static const std::ratio<NumerMax, DenomMax> max_;
public:
U const min = static_cast<U>(min_.num) / static_cast<U>(min_.den);
U const max = static_cast<U>(max_.num) / static_cast<U>(max_.den);
};
您可以始终将其包装在 ratio
中,这样您就可以编写 Limit<int, std:::ratio<100>, std::ratio<200>>
...
或者你可以按照
的方式做一些事情// if T is floating point, return std::intmax_t, otherwise T.
template<class T>
using adjust_floating = std::conditional_t<std::is_floating_point<T>{}, std::intmax_t, T>;
template <class T, adjust_floating<T> A1 = 0,
adjust_floating<T> A2 = 0,
adjust_floating<T> A3 = 0,
adjust_floating<T> A4 = 0 >
struct Limit {
// maybe static_assert that A3 and A4 are zero if T isn't floating point
static constexpr T min = std::is_floating_point<T>{} ? A1 / (T) A2 : A1;
static constexpr T max = std::is_floating_point<T>{} ? A3 / (T) A4 : A2;
};