简体   繁体   中英

Using a runtime parameter (variable) in C++ metaprogramming at compile-time

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)

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());

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM