C++標準属性まとめ

# はじめに
この記事は、[C++ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/cpp) の13日目です。
前日の記事は @Linus_MK さん
明日の記事は @shohirose さんです。

# 属性とは

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

# C++11

## noreturn 属性
`関数`

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


```cpp

[[noreturn]] void exit()
{
	std::exit(0);
}
int hoge(int x)
{
	if (x > 0) {
		return x;
	} // ifに入らない場合returnがないが
	exit(); // この関数は返らない
}
```
https://cpprefjp.github.io/lang/cpp11/attributes.html#noreturn
## carries_dependency属性
`関数` `関数パラメータ`

並列プログラミングのアトミック操作において、値に依存した順序付けを関数をまたいで伝搬することを示す属性。
[atomic](https://cpprefjp.github.io/reference/atomic/atomic.html)や[memory_order](https://cpprefjp.github.io/reference/atomic/memory_order.html)についてはここでは詳しく述べない。 ~~(使ったことがないので詳しく知らない)~~

```cpp
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;
}
```

https://cpprefjp.github.io/lang/cpp11/attributes.html#carries_dependency

# C++14

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


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

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

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

int main()
{
	old_func(); // warning
	return 0;
}
```
https://cpprefjp.github.io/lang/cpp14/deprecated_attr.html
# C++17

## fallthrough属性
`switch-case`

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

```cpp
int hoge(int i)
{
	int ret = 0;
	switch (i)
	{
	case 1: 
		ret += 1;
		[[fallthrough]]; // 意図的なフォールスルー
	case 2:
		ret += 2; 
		break;
	}
	return ret;
}
```
https://cpprefjp.github.io/lang/cpp17/fallthrough.html
## maybe_unused属性
`クラス` `タイプエイリアス` `列挙型` `関数` `関数パラメータ` 
`変数` `非静的メンバ変数` `列挙子` 

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

```cpp

void hoge([[maybe_unused]]int _unused)
{
	// _unusedは使用されない
}
```
https://cpprefjp.github.io/lang/cpp17/maybe_unused.html
## nodiscard属性
`関数`

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

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

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

int main()
{
	create(); // warning
	return 0;
}
```
https://cpprefjp.github.io/lang/cpp17/nodiscard.html

# C++20

## no_unique_address属性
`非静的メンバ変数`

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

```cpp

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;
}
```
https://cpprefjp.github.io/lang/cpp20/language_support_for_empty_objects.html
## likely, unlikely属性
`if` `switch-case`

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

```cpp:

	if (normal())[[likely]]
	{
		// 良く通る処理
	}
	if (rare())[[unlikely]]
	{
		// 滅多にとおらない処理
	}
```
https://cpprefjp.github.io/lang/cpp20/likely_and_unlikely_attributes.html
# C++23

## assume属性

`空文`

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

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

# C++26以降

## pre, post, assert属性(?)
契約プログラミングのための属性。まとまるまでは保留

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2660r0.pdf

<details><summary>old</summary>

## expects, ensures, assert属性
`関数`

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

関数に対して事前条件、事後条件、アサーションの契約を指定する属性。
契約に違反した場合[std::contract_violation](https://en.cppreference.com/w/cpp/error/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属性
関数に入る際の、その引数またはその他のオブジェクトの状態に期待することを定義。

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

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

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

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

```cpp
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

</details>




# さいごに

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


## 参考

- https://cpprefjp.github.io/lang/cpp11/attributes.html
- https://en.cppreference.com/w/cpp/language/attributes