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

Pub*_*bby 23 c++ user-defined-literals constexpr c++11

我正在测试用户定义的文字.我想让_fac返回数字的阶乘.

让它调用一个constexpr函数是有效的,但它不允许我用模板做,因为编译器抱怨参数不是也不可能constexpr.

我对此感到困惑 - 不是文字常量表达式吗?该55_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
}
Run Code Online (Sandbox Code Playgroud)

第二种方法:

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
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 11

我不知道C++ 11中有没有比当前接受的答案更好的方法,但是constexpr在C++ 14中放松,你可以编写"普通"代码:

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, "!");
Run Code Online (Sandbox Code Playgroud)


Pub*_*bby 5

这就是我最终这样做的方式:

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;
}
Run Code Online (Sandbox Code Playgroud)

非常感谢 KerrekSB!

  • 投反对票,因为答案并没有真正回答 OP 提出的问题,而只包含代码。 (2认同)