サーチ…
構文
[[details]]:単純な引数なしの属性
[[details(arguments)]]:引数を持つ属性
__attribute(詳細):非標準GCC / Clang / IBM固有
__declspec(詳細):標準以外のMSVC固有
[[返品不可]]
C ++ 11は[[noreturn]]
属性を導入しました。これは、関数がreturn文を実行するか、それが本体であれば末尾に達することによって関数が呼び出し元に戻らないことを示すために使うことができます( void
関数には当てはまらないことに注意することが重要です。呼び出し元に戻っても、値を返さない)。このような関数は、 std::terminate
またはstd::exit
呼び出すか、例外をスローすることで終了することがあります。このような関数はlongjmp
を実行することで戻ることができます。
例えば、以下の関数は常に例外をスローするか、 std::terminate
呼び出すので、 [[noreturn]]
良い候補です:
[[noreturn]] void ownAssertFailureHandler(std::string message) {
std::cerr << message << std::endl;
if (THROW_EXCEPTION_ON_ASSERT)
throw AssertException(std::move(message));
std::terminate();
}
この種の機能は、コードが実行されないことがわかっている場合、コンパイラがreturn文なしで関数を終了できるようにします。ここでは、下のコードのownAssertFailureHandler
(上で定義した)の呼び出しがownAssertFailureHandler
れないため、コンパイラはその呼び出しの下にコードを追加する必要はありません。
std::vector<int> createSequence(int end) {
if (end > 0) {
std::vector<int> sequence;
sequence.reserve(end+1);
for (int i = 0; i <= end; ++i)
sequence.push_back(i);
return sequence;
}
ownAssertFailureHandler("Negative number passed to createSequence()"s);
// return std::vector<int>{}; //< Not needed because of [[noreturn]]
}
関数が実際に返る場合は未定義の動作なので、次のことは許されません。
[[noreturn]] void assertPositive(int number) {
if (number >= 0)
return;
else
ownAssertFailureHandler("Positive number expected"s); //< [[noreturn]]
}
[[noreturn]]
は主にvoid関数で使用されることに注意してください。ただし、これは必須ではなく、関数を汎用プログラミングで使用することができます。
template<class InconsistencyHandler>
double fortyTwoDivideBy(int i) {
if (i == 0)
i = InconsistencyHandler::correct(i);
return 42. / i;
}
struct InconsistencyThrower {
static [[noreturn]] int correct(int i) { ownAssertFailureHandler("Unknown inconsistency"s); }
}
struct InconsistencyChangeToOne {
static int correct(int i) { return 1; }
}
double fortyTwo = fortyTwoDivideBy<InconsistencyChangeToOne>(0);
double unreachable = fortyTwoDivideBy<InconsistencyThrower>(0);
次の標準ライブラリ関数には、この属性があります。
- std :: abort
- std :: exit
- std :: quick_exit
- std :: unexpected
- std :: terminate
- std :: rethrow_exception
- std :: throw_with_nested
- std :: nested_exception :: rethrow_nested
[[fallthrough]]
switch
でcase
が終了するたびに、次のケースのコードが実行されます。この最後のものは、'break`ステートメントを使って防ぐことができます。このいわゆるフォールスルー動作は意図しないバグを引き起こす可能性があるため、いくつかのコンパイラとスタティックアナライザが警告を出します。
C ++ 17以降では、標準属性が導入され、コードが落ちるときに警告が不要であることが示されています。コンパイラは、 break
または[[fallthrough]]
を伴わずにケースが終了し、少なくとも1つのステートメントがある場合、警告を安全に与えることができます。
switch(input) {
case 2011:
case 2014:
case 2017:
std::cout << "Using modern C++" << std::endl;
[[fallthrough]]; // > No warning
case 1998:
case 2003:
standard = input;
}
[[fallthrough]]
をどのように使用できるかについてのより詳細な例については、提案を参照してください。
[[deprecated]]と[[deprecated( "reason")]]
C ++ 14では、属性を使用して関数を非推奨にする標準的な方法を導入しました。 [[deprecated]]
は、関数が非推奨であることを示すために使用できます。 [[deprecated("reason")]]
コンパイラが表示できる特定の理由を追加することができます。
void function(std::unique_ptr<A> &&a);
// Provides specific message which helps other programmers fixing there code
[[deprecated("Use the variant with unique_ptr instead, this function will be removed in the next release")]]
void function(std::auto_ptr<A> a);
// No message, will result in generic warning if called.
[[deprecated]]
void function(A *a);
この属性は次の場合に適用されます:
- クラスの宣言
- 型定義名
- 変数
- 非静的データメンバー
- 機能
- 列挙型
- テンプレートの特殊化
(ref.c ++標準草案 :7.6.5非推奨属性)
[[nodiscard]]
[[nodiscard]]
属性は、関数呼び出し時に関数の戻り値を無視しないことを示すために使用できます。戻り値が無視されると、コンパイラはこれについて警告を出す必要があります。属性は次の場所に追加できます。
- 関数定義
- Aタイプ
属性を型に追加するのは、この型を返すすべての単一の関数に属性を追加するのと同じ動作です。
template<typename Function>
[[nodiscard]] Finally<std::decay_t<Function>> onExit(Function &&f);
void f(int &i) {
assert(i == 0); // Just to make comments clear!
++i; // i == 1
auto exit1 = onExit([&i]{ --i; }); // Reduce by 1 on exiting f()
++i; // i == 2
onExit([&i]{ --i; }); // BUG: Reducing by 1 directly
// Compiler warning expected
std::cout << i << std::end; // Expected: 2, Real: 1
}
[[nodiscard]]
使用方法に関する詳細な例は、提案を参照してください。
注: Finally
/ onExit
の実装の詳細は、この例では省略されています( Finally / ScopeExitを参照)。
[[maybe_unused]]
[[maybe_unused]]
属性は、特定のロジックが使用されない可能性があることをコード内で示すために作成されます。これは、しばしば、これが使用される可能性のあるプリプロセッサ条件にリンクされているか、または使用されていない可能性があります。コンパイラは未使用の変数に対して警告を出すことができるので、これはインテントを示すことによってそれらを抑止する方法です。
プロダクションで不要な間にデバッグビルドで必要とされる変数の典型的な例は、成功を示す戻り値です。デバッグビルドでは、条件をアサートする必要がありますが、本番ではこれらのアサーションは削除されています。
[[maybe_unused]] auto mapInsertResult = configuration.emplace("LicenseInfo", stringifiedLicenseInfo);
assert(mapInsertResult.second); // We only get called during startup, so we can't be in the map
もっと複雑な例として、名前のない名前空間にあるヘルパー関数の種類があります。コンパイル時にこれらの関数を使用しないと、コンパイラによって警告が出されることがあります。理想的には、呼び出し元と同じプリプロセッサタグを使用してそれらを保護したいのですが、複雑になる可能性があるので、 [[maybe_unused]]
属性はより保守的な方法です。
namespace {
[[maybe_unused]] std::string createWindowsConfigFilePath(const std::string &relativePath);
// TODO: Reuse this on BSD, MAC ...
[[maybe_unused]] std::string createLinuxConfigFilePath(const std::string &relativePath);
}
std::string createConfigFilePath(const std::string &relativePath) {
#if OS == "WINDOWS"
return createWindowsConfigFilePath(relativePath);
#elif OS == "LINUX"
return createLinuxConfigFilePath(relativePath);
#else
#error "OS is not yet supported"
#endif
}
[[maybe_unused]]
使用方法に関する詳細な例は、提案を参照してください。