我正在测试用户定义的文字。我想让_fac
返回数字的阶乘。
让它调用constexpr
函数有效,但它不允许我使用模板,因为编译器抱怨参数不是,不能是constexpr
。
我对此感到困惑 - 不是文字常量表达式吗? 5
中的5_fac
始终是可以在编译期间进行评估的文字,为什么我不能这样使用它呢?
第一种方法:
constexpr int factorial_function(int x) {
return (x > 0) ? x * factorial_function(x - 1) : 1;
}
constexpr int operator "" _fac(unsigned long long x) {
return factorial_function(x); // this works
}
第二种方法:
template <int N> struct factorial_template {
static const unsigned int value = N * factorial_template<N - 1>::value;
};
template <> struct factorial_template<0> {
static const unsigned int value = 1;
};
constexpr int operator "" _fac(unsigned long long x) {
return factorial_template<x>::value; // doesn't work - x is not a constexpr
}
答案 0 :(得分:11)
我不知道C ++ 11中有没有比当前接受的答案更好的方法,但是在C ++ 14中放松constexpr
,你可以写&#34;正常&#34;代码:
constexpr unsigned long long int operator "" _fac(unsigned long long int x) {
unsigned long long int result = 1;
for (; x >= 2; --x) {
result *= x;
}
return result;
}
static_assert(5_fac == 120, "!");
答案 1 :(得分:4)
这就是我最终做到的方式:
template <typename t>
constexpr t pow(t base, int exp) {
return (exp > 0) ? base * pow(base, exp-1) : 1;
};
template <char...> struct literal;
template <> struct literal<> {
static const unsigned int to_int = 0;
};
template <char c, char ...cv> struct literal<c, cv...> {
static const unsigned int to_int = (c - '0') * pow(10, sizeof...(cv)) + literal<cv...>::to_int;
};
template <int N> struct factorial {
static const unsigned int value = N * factorial<N - 1>::value;
};
template <> struct factorial<0> {
static const unsigned int value = 1;
};
template <char ...cv>
constexpr unsigned int operator "" _fac()
{
return factorial<literal<cv...>::to_int>::value;
}
非常感谢KerrekSB!
答案 2 :(得分:4)
我可能错了,但我认为constexpr函数也可以使用非常量参数调用(在这种情况下,它们不会给出常量表达式并在运行时进行计算)。哪种方法不适用于非类型模板参数。
答案 3 :(得分:3)
为了将constexpr与用户定义的文字一起使用,您显然必须使用可变参数模板。请查看wikipedia article中的第二个列表以获取示例。
答案 4 :(得分:1)
@Pubby。消化char非类型参数包的简单方法是将其放入字符串的初始化列表中。然后你可以使用atoi,atof等:
#include <iostream>
template<char... Chars>
int
operator "" _suffix()
{
const char str[]{Chars..., '\0'};
return atoi(str);
}
int
main()
{
std::cout << 12345_suffix << std::endl;
}
请记住为C风格的函数添加空字符。