以非递归方式计算 10 的 constexpr 幂?

constexpr power of 10 in non-recursive way?

以递归方式实现 10 的 constexpr 次方非常容易:

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, "");

是否有可能以非递归方式计算 10 的 constexpr 次方?

仅供参考,我使用的 VS2015 不支持 C++14 中的 relaxed-constexpr,因此,我不能在 constexpr 函数中使用 for 循环。

因此,如果我理解正确,您编译了 C++14,但您的编译器并不完全兼容 C++14 constexpr 函数。所以你不能在 constexpr 函数中进行循环。

嗯...我没有你的编译器所以我不知道你的编译器到底不支持什么,所以我提出了一个基于非递归的 C++14 解决方案 constexpr 不使用 for 循环的可变参数模板函数。嗯...两个函数:一个用于负幂,一个用于非负幂。

希望VS2015支持

负函数如下

模板

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

他们通过以下方式被调用

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>{}); }

下面是一个完整的编译示例(但请注意,正如 n.m 所指出的那样,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, "!" );
 }

老实说,这个解决方案在 std::make_index_sequence.

中是(或可以是)有点递归的