7

更新:私は以下に自分の答えを投稿 しましたそしてこの問題のより長いバージョンがここにあります:http ://scrupulousabstractions.tumblr.com/post/38460349771/c-11-type-safe-use-of-integer-user-defined-リテラル

質問:

値をunsignedlonglongとして取得する単純なconstexprユーザー定義リテラルを作成しました(これが、ユーザー定義の数値リテラルの動作方法です:http: //en.cppreference.com/w/cpp/language/user_literal)。値がsignedlonglongに収まるようにしてください。_X

それはすべてうまく機能します(値が大きすぎるとコンパイルエラーが発生します)が、次のような変数を明示的に作成した場合に限ります

constexpr auto a= 150_X;

代わりに私が次のような典型的なものを書く場合

cout << 150_X << endl;;

テストはコンパイル時に実行されません。

  • constexpr関数は、constexpr変数に割り当てられている場合にのみ、コンパイル時に実行されますか?(私はそれを標準で見つけることができませんでした)

  • _X私が探しているものの安全な行動を達成することは可能ですか?

完全な例:

#include<iostream>
#include<stdexcept>

inline constexpr long long testConv(unsigned long long v) {
  return (v > 100 ) ? throw std::exception() : v; 
} // will eventually use actual limit from numeric_limits

inline constexpr long long operator "" _X(unsigned long long f) { 
  return testConv(f) ;
}

int main(){
  constexpr auto a= 5_X;
  std::cout << a << std::endl;
  std::cout << 200_X << std::endl;  // This bad literal is accepted at compile time
  constexpr auto c=250_X;           // This bad literal is not accepted at compile time
  std::cout << c << std::endl;
}

ああ、参考までに:私はgcc4.7.2を使用しました。

4

3 に答える 3

4

自己回答: 私の質問に対するコメントやその他の回答、およびhttps://stackoverflow.com/a/13384317/1149664などの他の質問に触発された完全な解決策を見つけました。

解決策は、ユーザー定義リテラルのテンプレート形式を使用し、数値を手動で合計して、すでに解析された桁に基づく合計に10を掛けることです。

私はこの自己回答の詳細なバージョンをここに書きました:http ://scrupulousabstractions.tumblr.com/post/38460349771/c-11-type-safe-use-of-integer-user-defined-literals

template<char... Chars>
int operator"" _steps(){
  return {litparser<0,Chars...>::value};
}

Litparserは、Charsパラメーターパックによって保持されている入力文字から展開された引数として文字のリストを取得する小さなテンプレートメタプログラムです。

typedef unsigned long long ULL;

// Delcare the litparser 
template<ULL Sum, char... Chars> struct litparser;

// Specialize on the case where there's at least one character left:
template<ULL Sum, char Head, char... Rest>
struct litparser<Sum, Head, Rest...> {
// parse a digit. recurse with new sum and ramaining digits
  static const ULL value = litparser<
    (Head <'0' || Head >'9') ? throw std::exception() : 
    Sum*10 + Head-'0' , Rest...>::value;
};

// When 'Rest' finally is empty, we reach this terminating case
template<ULL Sum>  struct litparser<Sum> {
  static const ULL value = Sum;
};
于 2012-12-13T22:33:25.400 に答える
3

constexpr関数コンパイル時に実行できます。つまり、定数式で使用するのに適しています定数式で使用しない場合は、許可されていると思いますが、コンパイル時に実行しても意味がありません。

パラメータを(セクション7.1.5 / 1)[1]として宣言することは許可されていないため、コンパイル時にconstexpr評価を強制する方法はないと思いますが、おそらく次のように宣言できます。operator "" _X(unsigned long long)template<char...> operator "" _X()

関数が定数式内で呼び出される場合constexpr、引数は定数式になります(そうでない場合、呼び出しは定数式ではありません)。ただし、パラメータをとして宣言することによって呼び出しを定数式にすることできません。パラメータをとして宣言することは許可されていないためです。標準への参照を参照してください。constexprconstexpr


[注1]:段落2の主張を正当化するために標準を検索してくれた@LightnessRacesInOrbitに感謝します。

于 2012-12-13T22:06:11.987 に答える
1

Constexpr関数は、コンパイル時に実行する必要はありません。しかし、あなたの目標は達成することができます。問題をよりよく理解し、コンパイル時に常に評価されるイテラルを作成する方法の例として、この投稿をお勧めします。

于 2012-12-13T22:56:00.157 に答える