24

ユーザー定義リテラルをテストしています。_fac数値の階乗を返すようにしたい。

関数を呼び出すことはconstexpr機能しますが、引数が ではなく、 ではないとコンパイラが不平を言うため、テンプレートでそれを行うことはできませんconstexpr

私はこれに混乱しています - リテラルは定数式ではありませんか? 5in5_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
}

2 番目の方法:

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
}
4

5 に答える 5

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

KerrekSBに感謝します!

于 2011-11-13T00:49:23.283 に答える
4

私は間違っているかもしれませんが、constexpr関数は非定数引数を使用して呼び出すこともできると思います(この場合、定数式を与えず、実行時に評価されます)。これは、型以外のテンプレート引数ではうまく機能しません。

于 2011-11-13T01:22:59.903 に答える
3

ユーザー定義のリテラルで constexpr を使用するには、可変個引数テンプレートを使用する必要があるようです。例として、ウィキペディアの記事の 2 番目のリストを見てください。

于 2011-11-12T23:58:11.230 に答える
1

@パビー。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 スタイルの関数にはヌル文字を追加することを忘れないでください。

于 2011-11-13T05:48:37.647 に答える