有没有办法为 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;
}
模板元编程的"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;
}