2014-05-22 39 views
1

是否有机会编写元编程功能,但不能扩展编译中的所有参数?只是想要一些参数作为运行时参数和一些编译。因为我知道其中一些将在1..10的范围内,但另一个未知(将在运行时知道)。编译时在C++元编程中使用运行时参数(变量)

允许使用标准的元编程例子:

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. 

而下面是我的情况:

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

我如何转换上面元编程?并运行此假设如下(或类似的东西):

// int variable; 
// variable = get_var_from_user(); 
// cutom_imagined_function<4>::value(variable) 
+1

你的例子没有意义。当factorial是一个只有一个参数的概念时,我该如何描述如何实现'factorial <4>(variable)'? –

+0

@MooingDuck这只是一个例子......编辑。更好? – nosbor

+0

@awesomeyi不能?你为什么想让编译器确定运行时间的东西? – nosbor

回答

4

您可以使用相同的方法:常量表达式成为模板参数,一切没有按“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; } 
}; 

用法:

unsigned int result = cutom_imagined<N>::function(get_input()); 
+0

这里所有的工作都是在运行时完成的,对吧?这仍然是元编程吗? – unicorn2

+0

@ unicorn2:只有运行时工作在运行时完成。编译时的东西是在编译时完成的。 –

+0

你能否详细说明一下。在nosbor的例子中,Factorial的结果被编译为结果值。 例如 int y =因子<6> ::值;看起来像:int y = 720;在.asm中的权利? – unicorn2

3

假设你的意思是这样的:

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

这里的一般概念,我觉得你描述。这其实很简单。使函数本身为模板。

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

或者,您可以使用稍微更详细的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); 
} 

此外,现在我们已经constexpr(在一些编译器反正),该factorial容易简化为:

constexpr unsigned int factorial(unsigned int n) { 
    return n==0?1:n*factorial(n-1); 
} 
+0

好吧,这是一个解决方案,但我想它不会扩展为原始因子。这是一个简单的模板,而不是元编程。 – nosbor

+0

@nosbor:“扩展”是什么意思?你的意思是去掉递归并利用'n'在编译时已知的事实?它已经做到了,它看起来不像它。 –

+0

@dyp:哦,诅咒,他们都这样做。谢谢 –