Reputation: 2999
Is there opportunity to make metaprogramming function but not expand all parameters in compilation? Just want to have some parameters as the runtime parameters and some compiles. Because I know that some of them will be in range of 1..10 but the other are unkown (will be known at runtime).
Lets use standard metaprogramming example:
unsigned int factorial(unsigned int n) {
return n == 0 ? 1 : n * factorial(n - 1);
}
template <int n>
struct factorial {
enum { value = n * factorial<n - 1>::value };
};
template <>
struct factorial<0> {
enum { value = 1 };
};
// Usage examples:
// factorial<0>::value would yield 1;
// factorial<4>::value would yield 24.
And below is my case:
unsigned int cutom_imagined_function(unsigned int n, unsigned int runtime_param /* this will be given at runtime */) {
return n == 0 ? 1 : (n + runtime_param) * cutom_imagined_function(n - 1);
}
how can I convert above to metaprogramming? And run this let's say as below (or something similar):
// int variable;
// variable = get_var_from_user();
// cutom_imagined_function<4>::value(variable)
Upvotes: 1
Views: 1223
Reputation: 66912
Assuming you meant this:
unsigned int cutom_imagined_function(
unsigned int n,
unsigned int runtime_param)
{
return n == 0 ? 1 : (n+runtime_param)*custom_imagined_function(n-1, runtime_param);
}
here's the general concept I think you're describing. It's actually pretty straightforward. Make the function itself a template.
template<unsigned int in>
unsigned int custom_imagined_function(unsigned int runtime_param) {
return (n+runtime_param)*custom_imagined_function<n-1>(runtime_param);
}
template<>
unsigned int custom_imagined_function<0>(unsigned int runtime_param) {
return 1;
}
int main() {
int variable;
std::cin >> variable;
unsigned int result = custom_imagined_function<4>(variable);
}
Alternatively, you can use the slightly more verbose std::integral_constant
.
unsigned int custom_imagined_function(
std::integral_constant<unsigned int,0>,
unsigned int runtime_param)
{
return 1;
}
template<unsigned int in>
unsigned int custom_imagined_function(
std::integral_constant<unsigned int,n>,
unsigned int runtime_param)
{
std::integral_constant<unsigned int,n-1> less;
return (n+runtime_param) * custom_imagined_function(less, runtime_param);
}
int main() {
std::integral_constant<unsigned int,4> four;
int variable;
std::cin >> variable;
unsigned int result = custom_imagined_function(four, variable);
}
Additionally, now that we have constexpr
(in some compilers anyway), the factorial
is easily simplified:
constexpr unsigned int factorial(unsigned int n) {
return n==0?1:n*factorial(n-1);
}
Upvotes: 3
Reputation: 476930
You can use the same approach: Constant expressions become template parameters, everything else doesn't:
template <unsigned int N>
struct cutom_imagined
{
static unsigned int function(unsigned int r)
{
return (N + r) * cutom_imagined<N - 1>::function(r);
}
};
template <>
struct cutom_imagined<0>
{
static unsigned int function(unsigned int) { return 1; }
};
Usage:
unsigned int result = cutom_imagined<N>::function(get_input());
Upvotes: 4