c ++的整数幂,模板元程序设计 [英] c++ power of integer, template meta programming
问题描述
我想创建一个返回整数幂的函数。
请阅读fmuecke的解决方案
c ++中的整数幂
但是,我想把他的解决方案推广到任意类型T.
由于c ++ 11有constexpr,我想这是可能。
朴素,我尝试了像
类T,
inline constexpr T pow(const T x){
return pow< N-1>(x)* x;
}
template< class T>
inline constexpr T pow< T,1>(const T x){
return x;
}
template< class T>
Inline constexpr T pow< T,0>(const T x){
return 1;
}
实际上,此方法失败,因为不允许函数模板的部分专门化。 / p>
又一个问题。我听说编译器是否在编译时评估constexpr函数是否由编译器决定。
如何强制它为一般类型的计算。
我从某处读到一个最简单的整数常量的hack是包装在std :: integral_const :: value。
解决方案使用递归:
#include< iostream>
template< class T>
inline constexpr T pow(const T base,unsigned const exponent)
{
//(下一行不需要括号)
return(exponent == 0)? 1:(base * pow(base,exponent-1));
}
int main()
{
std :: cout< pow(2,4):< pow(2,4)< std :: endl;
std :: cout<< pow(5,0):< pow(5,0)<< std :: endl;
}
Jeremy W. Murphy 建议/请求一个使用指数平方的版本:
template< class T>
inline constexpr T pow(const T base,unsigned const exponent)
{
//(下一行不需要括号)
return(exponent == 0)? 1:
(exponent%2 == 0)? pow(base,exponent / 2)* pow(base,exponent / 2):
base * pow(base,(exponent-1)/ 2)* pow
}
是由编译器确定的,不管是否在编译时对constexpr函数进行求值。
True,AFAIK。编译器不需要在编译时进行常数初始化,但是如果你使用constexpr函数的结果作为非类型模板参数,它必须在编译时计算结果。
std :: cout< std :: integral_constant< int,pow(2,4)> :: value<< std :: endl;
另请参阅使用 integral_constant
作为参数的方法 p>
以下是强制执行编译时评估的方法:
#include< ; iostream>
#include< type_traits>
//插入一个constexpr`pow'实现,例如。从上面的那个
模板<类型名T,T base,无符号指数>
using pow_ = std :: integral_constant< T,pow(base,exponent)>;
//宏==容易出错,你已被警告
#define POW(BASE,EXPONENT)(pow_< decltype(BASE),BASE,EXPONENT> :: value)
int main()
{
std :: cout< pow(2,4):< pow_< int,2,4> :: value< std :: endl;
std :: cout<< pow(2,4):< POW(2,4)<< std :: endl;
}
你downvote所以我可以提高我的回答。
I want to make a function which returns a power of integer. Please read the fmuecke's solution in power of an integer in c++ .
However, I want to generalize his solution to the arbitrary type T. Since c++11 has constexpr, I guess this is possible.
Naively, I tried something like,
template<class T, int N>
inline constexpr T pow(const T x){
return pow<N-1>(x) * x;
}
template<class T>
inline constexpr T pow<T, 1>(const T x){
return x;
}
template<class T>
inline constexpr T pow<T, 0>(const T x){
return 1;
}
Actually this approach failed since the partial specialization for function template is not allowed.
And one more question. I heard that it is up to the compiler whether the constexpr function is evaluated in compile time or not. How do I force it to compute for general type. I read from somewhere that one of the simplest hack for integral consts is to wrap it in std::integral_const::value.
Solution using recursion:
#include <iostream>
template<class T>
inline constexpr T pow(const T base, unsigned const exponent)
{
// (parentheses not required in next line)
return (exponent == 0) ? 1 : (base * pow(base, exponent-1));
}
int main()
{
std::cout << "pow(2, 4): " << pow(2, 4) << std::endl;
std::cout << "pow(5, 0): " << pow(5, 0) << std::endl;
}
Jeremy W. Murphy suggested/requested a version using exponentiation by squaring:
template<class T>
inline constexpr T pow(const T base, unsigned const exponent)
{
// (parentheses not required in next line)
return (exponent == 0) ? 1 :
(exponent % 2 == 0) ? pow(base, exponent/2)*pow(base, exponent/2) :
base * pow(base, (exponent-1)/2) * pow(base, (exponent-1)/2);
}
"I heard that it is up to the compiler whether the constexpr function is evaluated in compile time or not."
True, AFAIK. The compiler isn't required to do constant-initialization at compile-time, but if you use the result of a constexpr function as a non-type template argument, it has to compute the result at compile-time.
std::cout << std::integral_constant<int, pow(2, 4)>::value << std::endl;
Also see the approach using integral_constant
as parameter of pow
in Andy Prowl's answer.
Here's how you can enforce compile-time evaluation:
#include <iostream>
#include <type_traits>
// insert a constexpr `pow` implementation, e.g. the one from above
template < typename T, T base, unsigned exponent >
using pow_ = std::integral_constant < T, pow(base, exponent) >;
// macro == error prone, you have been warned
#define POW(BASE, EXPONENT) (pow_ < decltype(BASE), BASE, EXPONENT > :: value)
int main()
{
std::cout << "pow(2, 4): " << pow_<int, 2, 4>::value << std::endl;
std::cout << "pow(2, 4): " << POW(2, 4) << std::endl;
}
Please leave a comment if you downvote so I can improve my answer.
这篇关于c ++的整数幂,模板元程序设计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!