C++ 用户定义的文字参数不是constexpr?

C++ 用户定义的文字参数不是constexpr?,c++,c++11,constexpr,user-defined-literals,C++,C++11,Constexpr,User Defined Literals,我正在测试用户定义的文本。我想让\u fac返回数字的阶乘 让它调用constexpr函数是可行的,但是它不允许我使用模板,因为编译器抱怨参数不是而且不能是constexpr 我被这搞糊涂了-文字不是常量表达式吗?5\u fac中的5始终是一个可以在编译时计算的文本,所以为什么我不能这样使用它呢 第一种方法: constexpr int factorial_function(int x) { return (x > 0) ? x * factorial_function(x - 1)

我正在测试用户定义的文本。我想让
\u fac
返回数字的阶乘

让它调用
constexpr
函数是可行的,但是它不允许我使用模板,因为编译器抱怨参数不是而且不能是
constexpr

我被这搞糊涂了-文字不是常量表达式吗?
5\u 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
}
模板结构阶乘\u模板{
静态常量unsigned int value=N*factorial_template::value;
};
模板结构阶乘模板{
静态常量无符号整数值=1;
};
constexpr int运算符“”\u fac(无符号长x){
return factorial_template::value;//不起作用-x不是constexpr
}

为了将constexpr用于用户定义的文本,显然必须使用可变模板。以中的第二个列表为例。

我就是这样做的:

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;
}
模板
constexpr t pow(t base,int exp){
返回(exp>0)?base*pow(base,exp-1):1;
};
模板结构文字;
模板结构文字{
静态常量unsigned int到_int=0;
};
模板结构文字{
静态常量unsigned int to_int=(c-'0')*pow(10,sizeof…(cv))+literal::to_int;
};
模板结构阶乘{
静态常量unsigned int value=N*阶乘::value;
};
模板结构阶乘{
静态常量无符号整数值=1;
};
模板
constexpr无符号整数运算符“”\u fac()
{
返回阶乘::值;
}

非常感谢KerrekSB

我可能错了,但我认为constexpr函数也可以用非常量参数调用(在这种情况下,它们不提供常量表达式,并且在运行时进行计算)。这对非类型模板参数不起作用。

@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;
}
#包括
模板
int
运算符“”\u后缀()
{
常量字符str[]{Chars…,'\0'};
返回atoi(str);
}
int
main()
{

std::cout我不知道在C++11中是否有比当前公认的答案更好的方法,但是使用C++14中的relaxed
constexpr
,您可以编写“普通”代码:


我认为还没有任何编译器实现这些用户定义的文本。你是如何测试它的?很好!我还不知道它是受支持的。我在某个地方的机器上安装了其中一个,现在我很想解决这些可变模板:-)你不必总是使用可变模板来使用
constexpr
,但这种情况下不需要要求(但我知道你的意思)。我怎样才能将一个变量模板
char
转换为
int
?@Pubby-从中减去0x30?我不确定有没有更好的方法,但你可能可以使用部分模板专门化…尽管这个想法伤了我的头。为什么不包括一个例子,而不是参考维基百科?好吧,大概编译器会比较lain,如果你向函数传递了一个非编译时常量,那么这是否可以解决模板性一直渗透到代码层的问题?@MichaelPrice:当然,它可能会抱怨将非常量表达式传递给constexpr函数(正如我所说,我不确定我是否正确)。但这意味着您通常需要两个完全相同的函数,除了
constexpr
关键字之外,一个用于常量表达式,另一个用于所有其他表达式。问题在于,它不是
constexpr
。它实际上比将
unsigned long
作为参数类型传递更糟糕。Downvoting,因为答案并没有真正回答OPs提出的问题,只包含代码。
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, "!");