web-dev-qa-db-ja.com

ユーザー定義のリテラルでC ++ 14桁の区切り文字を使用できますか?

Clangが次の行をコンパイルしている間、g ++ 6.1は数字区切り文字について文句を言います( Coliruの実例 を参照):

auto time = 01'23s;

C++ 14標準(N3796)によると、どのコンパイラーが正しいですか?

それ以外の場合、数字区切り文字(§2.14.2)を許可するのは、<chrono>ライブラリ(§20.12.5.8)のユーザー定義リテラル(§2.14.8)の実装の詳細だけですか?これらのリテラルはunsigned long longパラメータで定義されているため、私見ではありません。

ハワード・ヒナントが例として10'000sを使用したことを覚えています CppCon2016トーク "A <chrono>チュートリアル" (彼のトークの約42分)。


(8進数のリテラル0123は偶然にのみ正しいである「1分23秒」をコーディングするつもりはなかったことに注意してください64 + 16 + 3 == 83。そのために私は書くべきです

auto time = 1min + 23s;

しかし、その考えられる誤解を招く解釈は問題の一部ではありません。)

42
René Richter

文法を見ると、ser-defined-integer-literaloctal-literal ud-suffixであり、octal-literalが定義されています。どちらかとして0または8進数-リテラル ’opt 8進数

N4140§2.14.8

ユーザー定義リテラル

  • ser-defined-integer-literal
  • [...]

ser-defined-integer-literal

  • 8進数-リテラルのud-サフィックス
  • [...]

N4140§2.14.2

8進数-リテラル

  • 0
  • 8進数-リテラル ’opt 8進数

そう 01'23sは完全に有効なリテラルです。

19
krzaq

@Aaron McDaidが示唆したように、これはGCCの<chrono>ライブラリの実装のバグのようです。 (現在未確認の)バグレポートがあります: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69905

GCCのlibstdc ++はstd::chrono_literalsの2つの署名を実装します:

constexpr chrono::duration<long double>
operator""s(long double __secs)
{ return chrono::duration<long double>{__secs}; }

template <char... _Digits>
  constexpr chrono::seconds
  operator""s()
  { return __check_overflow<chrono::seconds, _Digits...>(); }

エラーが発生するテンプレートバージョンは、標準では必要ありません。追加するとき

constexpr chrono::seconds
operator""s(unsigned long long __secs)
{ return chrono::seconds{__secs}; }

(私のローカルインストールの)<chrono>ヘッダーに、エラーが消えます。

ただし、GCCのライブラリ実装者は、このバージョンを意図的に省略している可能性があります。秒は次のように定義されているため、不要な署名なしから署名付きへの変換を防ぐことができます。

typedef duration<int64_t> seconds;

編集:

Jonathan Wakelyがバグレポートのコメントで最近指摘したように、実装は open Library Working Group issue に関連して設計によって選択されましたが、桁区切り記号は考慮されていませんでした。

5
René Richter

10進リテラルのWLOG:

[Lex.ext]

user-defined-integer-literal:
decimal-literalud-suffix

[Lex.icon]

decimal-literal
ゼロ以外の数字
decimal-literal opt数字

つまりはい、UDLでは数字区切り記号を使用できます。

5
Columbo