以非递归方式使用constexpr 10的幂?

时间:2018-06-25 16:11:48

标签: visual-studio-2015 c++14 template-meta-programming constexpr pow

以递归方式很容易实现constexpr的10的幂:

template<int exp, bool = (exp > 0)>
struct pow10 {
    static constexpr double value = pow10<exp - 1>::value * 10.0;
};

template<>
struct pow10<0, false> {
    static constexpr double value = 1.0;
};

template<int exp>
struct pow10<exp, false> {
    static constexpr double value = pow10<exp + 1>::value / 10.0;
};

template<int exp>
static constexpr double pow10_v = pow10<exp>::value;

static_assert(pow10_v<-3> == 1e-3, "");
static_assert(pow10_v<2> == 1e2, "");

是否可以以非递归方式使constexpr的幂为10?

仅供参考,我使用的是VS2015,它在C ++ 14中不支持轻松的constexpr,因此,我无法在constexpr函数中使用for循环。

1 个答案:

答案 0 :(得分:3)

因此,如果我理解正确,您可以编译C ++ 14,但是您的编译器并不完全符合C ++ 14 constexpr函数。因此,您无法在constexpr函数内部进行循环。

嗯...我没有您的编译器,所以我不知道您的编译器不支持什么功能,因此我提出了一种基于非递归{{1}不使用for循环的可变参数模板函数。嗯...两个功能:一个用于负幂,一个用于非负幂。

希望VS2015支持它。

负函数如下

模板

constexpr

非负数(对于正或零次方)几乎相等,但是使用constexpr T negPow10 (std::index_sequence<Is...> const &) { using unused = std::size_t[]; T ret { 1 }; (void)unused { 0U, (ret /= 10, Is)... }; return ret; } 而不是ret *= 10

通过以下

调用它们
ret /= 10

下面是一个完整的编译示例(但请注意,正如n.m.所指出的,template <typename T, int E, std::size_t N = (E < 0 ? -E : E)> constexpr T pow10 () { return E < 0 ? negPow10<T>(std::make_index_sequence<N>{}) : posPow10<T>(std::make_index_sequence<N>{}); } 上的static_assert()幂是不可靠的)

double

说实话,此解决方案在#include <utility> template <typename T, std::size_t ... Is> constexpr T posPow10 (std::index_sequence<Is...> const &) { using unused = std::size_t[]; T ret { 1 }; (void)unused { 0U, (ret *= 10, Is)... }; return ret; } template <typename T, std::size_t ... Is> constexpr T negPow10 (std::index_sequence<Is...> const &) { using unused = std::size_t[]; T ret { 1 }; (void)unused { 0U, (ret /= 10, Is)... }; return ret; } template <typename T, int E, std::size_t N = (E < 0 ? -E : E)> constexpr T pow10 () { return E < 0 ? negPow10<T>(std::make_index_sequence<N>{}) : posPow10<T>(std::make_index_sequence<N>{}); } int main () { static_assert( pow10<long, 5>() == 1e5, "!" ); static_assert( pow10<double, -3>() == 1e-3, "!" ); } 中是(或可以是)一点递归。