Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用隐式模板类型推断_C++_Templates_Template Meta Programming_Decltype - Fatal编程技术网

C++ 如何使用隐式模板类型推断

C++ 如何使用隐式模板类型推断,c++,templates,template-meta-programming,decltype,C++,Templates,Template Meta Programming,Decltype,我试图编写一个模板来计算编译时数字的幂(我不是一个模板元编程专家,所以任何评论都值得赞赏)。代码如下: template<typename T, T X, uint64_t P> struct Pow { static constexpr T result = X * Pow<T,X, P - 1>::result; }; template<typename T, T X> struct Pow<T, X, 0> { static

我试图编写一个模板来计算编译时数字的幂(我不是一个模板元编程专家,所以任何评论都值得赞赏)。代码如下:

template<typename T, T X, uint64_t P>
struct Pow
{
    static constexpr T result = X * Pow<T,X, P - 1>::result;
};
template<typename T, T X>
struct Pow<T, X, 0>
{
    static constexpr T result = 1;
};
template<typename T, T X>
struct Pow<T, X, 1>
{
    static constexpr T result = X;
};

我已经阅读了下面的内容,但到目前为止我还没有找到答案(似乎正好相反),并且。

从C++17开始,您可以使用
auto
类型作为
X
模板值

template <auto X, int64_t P>
struct Pow
{
    static constexpr decltype(X) result = X * Pow<X, P - 1>::result;
};

template <auto X>
struct Pow<X, 0>
{
    static constexpr decltype(X) result = 1;
};

<>当然可以跳过DECKTYPE,并且在使用C++ 11上下文时不需要任何结构。例如:

Pow<4, 2>::result
#include <iostream>
#include <type_traits>

template<typename T, class = typename std::enable_if< std::is_arithmetic<T>::value >::type >
constexpr T pow(T n, T power) noexcept {
    return power == 1 ? n : n * pow(n,power - 1);
}

int main(int argc, const char* argv) {

    static_assert( 4 == pow(2,2) ,"wrong pow");
    static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
    static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");

    std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
    std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
    std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;

    return 0;
}
#包括
#包括
模板::类型>
constexpr T pow(tn,T power)无例外{
返回功率==1?n:n*pow(n,功率-1);
}
int main(int argc,const char*argv){
静态_断言(4==pow(2,2),“错误pow”);
静态_断言(8.0F==功率(2.0F,3.0F),“错误功率”);
静态_断言(256.0==pow(2.0,8.0),“错误pow”);

std::cout不是一个模板类,但在您的情况下,
constexpr
函数是否也能同样好地工作?谢谢您的回答。我也在研究这个问题,但我发现很难强制它以constrexpr的方式使用。这就是代码的样子:模板constexpr T Pow(T num,unsigned int Pow){return pow==0?1:num*pow(num,pow-1);}所需要的只是您现有的模板类,如问题所示,以及一个返回
Pow::result
constepr
函数;在编译时,该函数在逻辑上等同于您所拥有的。我有点害怕人们在std::cout中使用它,也许指数应该是无符号类型,不是有符号类型。它将在
Pow
上中断。谢谢你的回答。我也读了这篇文章,但我有一个问题。没有静态断言位,就无法保证计算的编译时间。这是正确的吗?所以在类似
long double foo(long double bar,float buz){return log(bar,MATH\u PI)*Pow的情况下(bar,sqrt(buz));}
关闭,因为它不是一个编译时。但在这种情况下,我认为-它不应该是一个编译时。不像像
static constexpr long double FOO=pow(128.0500.0D)这样的东西
;顺便说一句,检查编译器程序集输出的最佳方法。如果您希望在
pow
的参数不是constexpr时出现编译时错误,那么在编译时上下文中调用函数时,您只需
静态断言(n==n,“not constexpr call”);静态断言(power==power,“not constexpr call”);
(通过将结果存储为
constexpr
或使用
static\u assert
)编译器将自动使用某种“no constexpr”消息无法编译。我在检查常量参数时看不到任何值…“部分专门化是多余的”…除非
T
是一个表示某种数学环的类类型,没有单位或半群,或者出于某种原因,不支持表达式
1
@aschepler-良好的点进行初始化…从理论角度…但是,实际上,如果
T
类型be模板参数,不能接受来自
1
的初始化,但支持乘法?
#define PowMacro(X, P)  Pow<decltype(X), X, P> 
#include <iostream>
#include <type_traits>

template<typename T, class = typename std::enable_if< std::is_arithmetic<T>::value >::type >
constexpr T pow(T n, T power) noexcept {
    return power == 1 ? n : n * pow(n,power - 1);
}

int main(int argc, const char* argv) {

    static_assert( 4 == pow(2,2) ,"wrong pow");
    static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
    static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");

    std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
    std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
    std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;

    return 0;
}
#include <iostream>
#include <type_traits>

// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
template<typename T>
constexpr T pow(const T base,const T power, typename std::enable_if< std::is_integral<T>::value >::type* = 0) {
    return  1 == power
            ? base
            : 0 == power
              ? 1
              : (1 == (power & 1) )
                ? base * pow(base, power - 1)
                : pow(base, (power >> 1) ) * pow( base, (power >> 1) );
}


#ifdef __GNUG__

  // GCC able to use most of <cmath> at compile time, check <cmath> header

  inline constexpr float pow(float base, float power) noexcept {
    return __builtin_powf(base, power);
  }

  inline constexpr double pow(double base, double power) noexcept {
    return __builtin_pow(base, power);
  }

  inline constexpr long double pow(long double base,long double power) noexcept {
    return __builtin_powl(base, power);
  }

#else

// slow
template<typename T>
constexpr T pow(T base, T power, typename std::enable_if< std::is_floating_point<T>::value >::type* = 0) noexcept {
    return power == 1.0 ? base : base * pow(base,power - static_cast<T>(1.0) );
}

#endif // __GNUG__


int main(int argc, const char** argv) {

    static_assert( 4 == pow(2,2) ,"wrong pow");
    static_assert( 1024 == pow(2L,10L) ,"wrong pow");
    static_assert( (1 << 20) == pow(2LL,20LL) ,"wrong pow");

    std::cout << "integer 2^1=" << pow(2, 1) << std::endl;
    std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
    std::cout << "long 2^10=" << pow(2L, 10L) << std::endl;
    std::cout << "long long 2^20=" << pow(2LL, 20LL) << std::endl;

    static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
    static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");
    static_assert( 1024.0L == pow(2.0L,10.0L) ,"wrong pow");

    std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
    std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;
    std::cout << "long double 2^10=" << pow(2.0L, 10.0L) << std::endl;

    return 0;
}