有没有办法为 C++ 中的模板函数动态赋值?

Is there a way to give dynamically values to to a templated function in C++?

模板元编程的"hello, world"可以认为是阶乘代码:

template <unsigned int n>
struct factorial {
    enum { value = n * factorial<n - 1>::value };
};

template <>
struct factorial<0> {
    enum { value = 1 };
};

所以我们可以通过

得到阶乘
cout << factorial<4>::value << endl; //It will print 24

但如果我这样做:

int N = 4;
cout << factorial<N>::value << endl; //COMPILE ERROR

有没有办法为 C++ 中的模板函数动态赋值?

不,你不能那样做。模板元编程的全部要点是在编译时进行一些计算。阶乘示例的整个递归展开链由编译器完成,因此它必须知道 n 的值才能完成计算。

当您直到运行时才知道 n 的值时,"regular" 编程风格适用,因此调用 factorial<N>::value 变得不必要。

最好的是:

constexpr int N = 4;
std::cout << factorial<N>::value << std::endl;

但是您将无法在 运行 时修改 N,所以我想除了举个小例子,它没有多大帮助。

这可能适合你。

#include<iostream>
#include<array>
#include<utility>

//Only >=c++14 supports doubles in constexpr, so we're sticking to integers.
template<unsigned int I>
struct FAC {
    static constexpr uint64_t val = I * FAC<I-1>::val;
};

template<>
struct FAC<0> {
    static constexpr uint64_t val = 0;
};

template<>
struct FAC<1> {
    static constexpr uint64_t val = 1;
};

template<size_t ... I>
uint64_t factorial_impl(std::index_sequence<I...>, const unsigned int i) {
    constexpr std::array<uint64_t, sizeof...(I)> a = {FAC<I>::val...};

    return a[i];
}

uint64_t factorial(const unsigned int i) {
    return factorial_impl(std::make_index_sequence<22>(), i); //Can't store factorial values above index 22 without using floating-point values
}

int main() {
    std::cout << "Which factorial do you want? [1-22]: ";
    unsigned int index = 0;
    std::cin >> index;
    std::cout << "Value of " << index << " is " << factorial(index) << std::endl;
    return 0;
}

如果您希望它与双打一起工作,您将需要一个兼容 c++14 的编译器,但这个轻微的修改应该可以工作:

#include <iostream>
#include<array>
#include<utility>

template<unsigned int I>
struct FAC {
    static constexpr double val = I * FAC<I-1>::val;
};

template<>
struct FAC<0> {
    static constexpr double val = 0;
};

template<>
struct FAC<1> {
    static constexpr double val = 1;
};

template<size_t ... I>
double factorial_impl(std::index_sequence<I...>, const unsigned int i) {
    constexpr std::array<double, sizeof...(I)> a = {FAC<I>::val...};

    return a[i];
}

double factorial(const unsigned int i) {
    return factorial_impl(std::make_index_sequence<170>(), i); //Values above 170 are infinite.
}

int main() {
    std::cout << "Which factorial do you want? [1-170]: ";
    unsigned int index = 0;
    std::cin >> index;
    std::cout << "Value of " << index << " is " << factorial(index) << std::endl;
    return 0;
}