用户定义的文字参数不是constexpr
User defined literal arguments are not constexpr?
我正在测试用户定义的文字。我想让_fac
返回这个数的阶乘
让它调用constexpr
函数工作,但是它不让我用模板做,因为编译器抱怨参数不是也不能是constexpr
。
我对此感到困惑-字面量不是常量表达式吗?5_fac
中的5
始终是一个可以在编译时计算的文字,那么为什么我不能这样使用它呢?
第一个方法:
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
}
我不知道在c++ 11中是否有比当前接受的答案更好的方法来做到这一点,但是在c++ 14中使用宽松的constexpr
,您可以编写"正常"代码:
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, "!");
我是这样做的:
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!
我可能错了,但我认为constexpr函数也可以用非常量参数调用(在这种情况下,它们不给出常量表达式,并在运行时进行评估)。这对于非类型模板参数就不太管用了。
为了使用constexpr和用户定义的字面值,显然必须使用可变的模板。请查看wikipedia文章中的第二个清单作为示例。
@Pubby。消化char非类型参数包的简单方法是将其包含到字符串的初始化列表中。然后你可以使用atoi, atof等:
#include <iostream>
template<char... Chars>
int
operator "" _suffix()
{
const char str[]{Chars..., ' '};
return atoi(str);
}
int
main()
{
std::cout << 12345_suffix << std::endl;
}
记住为c风格的函数附加一个空字符。
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- Constexpr 可变参数模板,用于对无符号整数进行重新排序
- MSVC 和函数参数的 constexpr?
- 使用constexpr + auto作为返回和参数类型的奇怪类型推导
- constexpr 函数的常量引用参数:gcc/msvc vs clang/icc
- 从非类型模板参数声明 constexpr 数组的可移植方法
- 为什么带有指针子对象的文字类类型的 constexpr 表达式不能是非类型模板参数
- 调用模板参数 constexpr 方法?
- constexpr 运算符重载使用参数的问题
- 使用模板参数还包括 constexpr 成员函数enable_if单独定义和声明模板成员函数
- 当迭代器(输入参数)通常不是constexpr时,constexpr算法真的有用吗
- 类成员参数中的Constexpr
- MSVC使用constexpr-if从可变模板方法中的基本模板参数中吞下const
- 在if constexpr中使用带参数包的概念时,升级到gcc 9后出现编译错误
- 在 constexpr-if 条件下比较 constexpr 函数参数会导致错误
- 不接受静态成员函数作为 constexpr 参数
- ODR-使用转发的 constexpr 参数
- 为什么不允许使用'constexpr'参数?
- 如果直接使用 constexpr-function,则认为 constexpr 参数,但如果用于调用另一个 conste
- 代码中奇怪的constexpr参数