47
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C++Advent Calendar 2018

Day 13

C++標準属性まとめ

Last updated at Posted at 2018-12-12

はじめに

この記事は、C++ Advent Calendar 2018 の13日目です。
前日の記事は @Linus_MK さん
明日の記事は @shohirose さんです。

属性とは

属性はコンパイラに追加の情報を伝えるための構文で、[[attributes]] といった書き方をする。
最適化や、警告の追加や抑制等ができる。

C++11

noreturn 属性

関数

関数が決して返らないことを示す属性。
例外送出やstd::exit, std::abortのラッパー関数に付ける。
これにより関数が返らないパスがある場合の警告を抑制する。


[[noreturn]] void exit()
{
	std::exit(0);
}
int hoge(int x)
{
	if (x > 0) {
		return x;
	} // ifに入らない場合returnがないが
	exit(); // この関数は返らない
}

carries_dependency属性

関数 関数パラメータ

並列プログラミングのアトミック操作において、値に依存した順序付けを関数をまたいで伝搬することを示す属性。
atomicmemory_orderについてはここでは詳しく述べない。 (使ったことがないので詳しく知らない)

struct Hoge 
{
	int hoge = 0;
};
std::atomic<Hoge*> x(nullptr);

[[carries_dependency]] Hoge* is_load()
{
	return x.load(std::memory_order_consume);
}

int main()
{
	std::thread th([]() {
		x.store(new Hoge{ 100 }, std::memory_order_release);
	});

	Hoge* pHoge = is_load();
	if (pHoge)
	{
		std::cout << pHoge->hoge;
	}
	th.join();
	return 0;
}

C++14

deprecated属性

クラス タイプエイリアス 列挙子 関数 テンプレート特殊化
変数 非静的メンバ変数 列挙型(C++17) 名前空間(C++17)

対象の機能が非推奨であることを示す属性。
API開発時等で非推奨になった機能に使用することで、ユーザーに警告として示すことができる。

引数として表示する警告文を指定することができる。
deprecated("reason")

[[deprecated("please use new_func() function")]]
void old_func(){}
void new_func(){}

int main()
{
	old_func(); // warning
	return 0;
}

C++17

fallthrough属性

switch-case

switch文においてフォールスルーであることを明示する属性。
意図的なフォールスルーの箇所に指定することで警告の抑制ができる。

int hoge(int i)
{
	int ret = 0;
	switch (i)
	{
	case 1: 
		ret += 1;
		[[fallthrough]]; // 意図的なフォールスルー
	case 2:
		ret += 2; 
		break;
	}
	return ret;
}

maybe_unused属性

クラス タイプエイリアス 列挙型 関数 関数パラメータ
変数 非静的メンバ変数 列挙子

未使用なものを明示する属性。
意図的に未使用なものに指定することで警告の抑制ができる。


void hoge([[maybe_unused]]int _unused)
{
	// _unusedは使用されない
}

nodiscard属性

関数

関数の戻り値を破棄してはならないことを示す属性。
破棄された場合警告文がでる。

引数として表示する警告文を指定することができる。
nodiscard("reason") (C++20以降)

[[nodiscard]]int * create()
{
	return new int(0);
}

int main()
{
	create(); // warning
	return 0;
}

C++20

no_unique_address属性

非静的メンバ変数

データメンバがそのクラスの他のすべての非静的データメンバと異なるアドレスを持つ必要がないことを示す属性


struct Empty{};

struct Test
{
	int x;
	Empty _noused;
};

struct Test2
{
	int x;
	[[no_unique_address]] Empty _noused;
};

int main()
{
	static_assert(sizeof(Empty) >= 1);

	static_assert(sizeof(Test) >= sizeof(int) + 1);

	static_assert(sizeof(Test2) == sizeof(int));

	return 0;
}

likely, unlikely属性

if switch-case

条件分岐で頻度を示す属性。
分岐が選ばれやすい場合はlikely、選ばれにくい場合はunlikelyを指定することで最適化のヒントにする。


	if (normal())[[likely]]
	{
		// 良く通る処理
	}
	if (rare())[[unlikely]]
	{
		// 滅多にとおらない処理
	}

C++23

assume属性

空文

関数が満たすべき仮定を指定することで、最適化のヒントとする。
引数に渡す式は効果がないが、評価結果がfalseの場合は未定義動作になる

int f(int y)
{
  // 効果を持たないため変数 y の値は変化しない。
  [[assume(++y == 43)]];
  // 最適化により return 42; へと置換される可能性がある。
  return y;
}

C++26以降

pre, post, assert属性(?)

契約プログラミングのための属性。まとまるまでは保留

old

expects, ensures, assert属性

関数

以下まだ勉強不足なのでさらっと見た感じ
むしろ教えて欲しい。。

関数に対して事前条件、事後条件、アサーションの契約を指定する属性。
契約に違反した場合std::contract_violationが生成されハンドラに渡される。

構文

[[expects contract-level: expression]]
[[ensures contract-level identifier: expression]]
[[assert contract-level: expression]]

  • contract-level: 契約レベル(後で記述)
  • expression: boolに変換可能な式
  • identifier: 関数の戻り値を表すための識別子

contract-level

default

特に指定がない場合これになる。
実行時チェックのコストが関数を実行するコストと比較して小さいと想定される場合使用。

audit

実行時チェックのコストが関数を実行するコストと比較して大きいと想定される場合使用。

axiom

形式的なコメントであり、実行時チェックをしない場合に使用。
ただし、コード静的解析ツールのために利用されるそう。

expect属性

関数に入る際の、その引数またはその他のオブジェクトの状態に期待することを定義。

// 引数には正の数のみ許容
int f(int x)[[expects: x > 0]];

ensures属性

関数から出る際の、その戻り値またはその他のオブジェクトの状態に期待することを定義。

// 戻り値には正の数のみ許容
int g(int x)[[ensures ret: ret > 0]];

assert属性

関数本体内で、満たされるべき条件を定義。
他二つとは記述場所が違う点注意。
今後assertマクロの代わりになりそうな認識でいる。

void p(int x,int y)
{
	// do something...

	[[assert:x + y > 0]];

	// do something...
}

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0542r0.html

さいごに

今回は属性をまとめてみました。
C++20のやつ等まだ使ったことないやつは自信もないので、間違っている点等ありましたら教えていただけると幸いです。

参考

47
30
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?