13

C++ Extensions for Library Fundamentals、バージョン 2 ( N4564 ) では type が導入されていstd::experimental::source_locationます。

§ 14.1.2 [reflection.src_loc.creation] は次のように述べています。

static constexpr source_location current() noexcept;

戻り値: postfix-expressionが (括弧で囲まれている可能性がある) id-expression Namingである関数呼び出し (C++14 § 5.2.2) によって呼び出されると、実装定義の値を持つ をcurrent返します。source_location値は、 および と#line同じ方法で (C++14 § 16.4) の影響を受ける必要が__LINE__あり__FILE__ます。他の方法で呼び出された場合、返される値は規定されていません。

備考:ブレースまたはイコール初期化子を使用して非静的データ メンバーを初期化する場合、すべての呼び出しは、currentメンバーを初期化するコンストラクターまたは集約の初期化の場所に対応する必要があります。

[注:デフォルトの引数 (C++14 § 8.3.6) として使用される場合、の値は呼び出しサイトでの呼び出しsource_locationの場所になりcurrentます。—エンドノート]

私の理解が正しければ、この機能はこのように使用されることを意図しています。

#include <experimental/source_location>  // I don't actually have this header
#include <iostream>
#include <string>
#include <utility>

struct my_exception
{

  std::string message {};
  std::experimental::source_location location {};

  my_exception(std::string msg,
               std::experimental::source_location loc = std::experimental::source_location::current()) :
    message {std::move(msg)},
    location {std::move(loc)}
  {
  }

};

int
do_stuff(const int a, const int b)
{
  if (a > b)
    throw my_exception {"a > b"};  // line 25 of file main.cxx
  return b - a;
}

int
main()
{
  try
    {
      std::cout << do_stuff(2, 1) << "\n";
    }
  catch (const my_exception& e)
    {
      std::cerr << e.location.file_name() << ":" << e.location.line() << ": "
                << "error: " << e.message << "\n";
    }
}

期待される出力:

main.cxx:25: error: a > b

がなければ、例外オブジェクトを適切に初期化するためにおよびマクロを内部的にstd::experimental::source_location使用するヘルパー マクロを使用した可能性があります。THROW_WITH_SOURCE_LOCATION__FILE____LINE__

ライブラリがどのように実装できるのか疑問に思っていましたstd::experimental::source_location。私が要点を完全に見逃していない限り、そうするのは特別なコンパイラ サポートなしでは不可能です。しかし、これを機能させるには、どのような魔法のコンパイラ機能が必要でしょうか? に展開されたトリックに匹敵しstd::initializer_listますか?この機能の実験的な実装はありますか? GCC の SVN ソースを確認しましたが、まだ何も見つかりませんでした。

4

1 に答える 1

15

これを実装するには、コンパイラからのサポートが必要です。たとえば、gccでは、次のような組み込み関数を使用できる可能性があります

   int __builtin_LINE()

この関数は、プリプロセッサ マクロに相当し__LINE__、ビルトインの呼び出しの行番号を返します。関数 の C++ デフォルト引数ではF、 への呼び出しの行番号を取得しFます。

   const char * __builtin_FUNCTION()

この関数は、プリプロセッサ マクロと同等__FUNCTION__であり、ビルトインの呼び出しが含まれる関数名を返します。

   const char * __builtin_FILE()

この関数は、プリプロセッサ マクロと同等__FILE__であり、ビルトインの呼び出しが含まれるファイル名を返します。関数 の C++ デフォルト引数でFは、呼び出しのファイル名を取得しますF

于 2015-12-21T23:23:53.400 に答える