description: C++20 ã®æ°ããè¨èªæ©è½ã¨æ¨æºã©ã¤ãã©ãªæ©è½ã®è§£èª¬
# C++20 ã®æ°æ©è½
!!! Info
é
ç®è¿½å ã»å·ç使¥ä¸ã§ãï¼å®æåº¦ ç´ 35%ï¼
C++20 è¦æ ¼ã«ãããæ°æ©è½ã»ä»æ§å¤æ´ã解説ãã¾ãã
## è¨èªæ©è½
### ããããã£ã¼ã«ãã«ããã©ã«ãã®åæå¤ãè¨å®å¯è½ã« [(P0683R1)](http://wg21.link/p0683r1)
ããããã£ã¼ã«ãã«ããããããå¹
ã®æå®ã«ç¶ãã¦ã`=` æ¼ç®åã¾ã㯠`{}` åæååã使ã£ã¦åæåå¼ãè¨è¿°ã§ããããã«ãªãã¾ãã
```C++
#include
enum class Terrain : unsigned char
{
Open, Forest, Hill, Mountain, Desert, Tundra, River, Ocean
};
struct Tile
{
unsigned char height : 4 = 1; // ããã©ã«ãå¤ã 1 ã«
Terrain terrain : 3 = Terrain::Open; // ããã©ã«ãå¤ãæç¤ºçã« Terrain::Open ã«
bool passable : 1 = true; // ããã©ã«ãå¤ã true ã«
};
int main()
{
std::cout << std::boolalpha;
Tile tile1;
std::cout << static_cast(tile1.height) << ", " << static_cast(tile1.terrain) << ", " << tile1.passable << '\n';
Tile tile2{ 15, Terrain::Mountain, false };
std::cout << static_cast(tile2.height) << ", " << static_cast(tile2.terrain) << ", " << tile2.passable << '\n';
}
```
```
1, 0, true
15, 3, false
```
### ã¡ã³ããã¤ã³ã¿æ¼ç®åã®ä»æ§ãä¸è²«æ§ã®ããã«ä¿®æ£ [(P0704R1)](http://wg21.link/p0704r1)
C++17 ã¾ã§ã®ã¡ã³ããã¤ã³ã¿æ¼ç®å `.*` ã¯ãå³è¾ºå¤ãªãã¸ã§ã¯ãããã左辺å¤åç
§ä¿®é£¾ãããã¡ã³ã颿°ãã¤ã³ã¿ã«ä½¿ããã¨ã¯ä¸é©æ ¼ãã¨ããè¦æ ¼æé¢ã«ãªã£ã¦ãã¾ããããã®ãããåãæå³ããã¤æ¬¡ã® 2 ã¤ã®ããã°ã©ã ã§å¾è
ã ãä¸é©æ ¼ã¨ãããä¸è²«æ§ãããã¾ããã§ããã
```C++
#include
#include
struct Text
{
std::string m_data;
const std::string& get() const &
{
return m_data;
}
};
int main()
{
std::cout << Text{ "Hello" }.get() << '\n'; // OK
std::cout << (Text{ "Hello" }.*&Text::get)() << '\n'; // C++17 ã¾ã§ã¯ä¸é©æ ¼ãC++20 ãã OK
}
```
C++20 ã§ã¯ãå³è¾ºå¤ãªãã¸ã§ã¯ãããã左辺å¤åç
§ä¿®é£¾ããã "é const" ã¡ã³ã颿°ãã¤ã³ã¿ã«ä½¿ããã¨ã¯ä¸é©æ ¼ãã¨æé¢ãä¿®æ£ããå¾è
ãã³ã³ãã¤ã«ã§ããããã«ãªãã¾ãã
### 符å·ä»ãæ´æ°åã®è² æ°è¡¨ç¾ã 2 ã®è£æ°ã¨è¦å® [(P1236R1)](http://wg21.link/p1236r1)
ã»ã¼ãã¹ã¦ã®ç¾ä»£çãªã³ã³ãã¥ã¼ã¿ã§ã符å·ä»ãæ´æ°åã®è² æ°ã¯ 2 ã®è£æ°ã§è¡¨ç¾ããã¾ããããããC++ ã§ã¯è² æ°ã®è¡¨ç¾æ¹æ³ã«ã¤ãã¦è¦æ ¼ã§å®ãã¦ããªãã£ããããï¼ç¾å®çã§ã¯ããã¾ãããï¼2 ã®è£æ°ä»¥å¤ã§è² æ°è¡¨ç¾ãå®è£
ããä½å°ãæ®ããã¦ãã¾ãããC++20 ãã㯠2 ã®è£æ°ã®ã¿ã許å¯ããããè¦æ ¼æè¨ãä¿®æ£ããã¾ããã
è¿å¹´ã®ã¢ã¼ããã¯ãã£ã§ 2 ã®è£æ°ä»¥å¤ã使ãä¾ã¯ã1 ã®è£æ°ã使ã Unisys 2200 ãããã¾ããã¾ãéå»ã«ã¯ç¬¦å·ã¨çµ¶å¯¾å¤ã§è¡¨ç¾ããã¢ã¼ããã¯ãã£ãããã¾ããããããã¯ã¢ãã³ãª C++ ãéçºç°å¢ã¨ãã¦ä½¿ç¨ããªãã®ã§ããã®è¦æ ¼å¤æ´ã«ããå½±é¿ã¯ç¡ãã¨èãããã¾ãã
#### ï¼åèï¼ç¬¦å·ä»ã 8-bit æ´æ°ã® 2 é²è¡¨ç¾
| 10 é²è¡¨ç¾ | 2 ã®è£æ° | 1 ã®è£æ° | 符å·ã¨çµ¶å¯¾å¤ |
|-------|----------|----------|----------|
| 127 | 01111111 | 01111111 | 01111111 |
| 126 | 01111110 | 01111110 | 01111110 |
| 125 | 01111101 | 01111101 | 01111101 |
| 2 | 00000010 | 00000010 | 00000010 |
| 1 | 00000001 | 00000001 | 00000001 |
| 0 | 00000000 | 00000000 | 00000000 |
| -0 | | 11111111 | 10000000 |
| -1 | 11111111 | 11111110 | 10000001 |
| -2 | 11111110 | 11111101 | 10000010 |
| -126 | 10000010 | 10000001 | 11111110 |
| -127 | 10000001 | 10000000 | 11111111 |
| -128 | 10000000 | | |
### ã¡ã³ãã®ãªãã¸ã§ã¯ãã空ã®ã¯ã©ã¹ã®å ´åã«ã¡ã¢ãªæ¶è²»ã 0 ã«ã§ãã `[[no_unique_address]]` 屿§ã追å [(P0840R2)](http://wg21.link/p0840r2)
ã¢ãã±ã¼ã¿ãªã©ãã¯ã©ã¹ã®ã¡ã³ãã¨ãã¦ä¿æããã¨ãããããã¹ãã¼ãã¬ã¹ãªç©ºã®ã¯ã©ã¹ã§ãã£ã¦ããªãã¸ã§ã¯ãã®ã¢ãã¬ã¹ã䏿ã«ç¨æããªãã¨ãããªãããããµã¤ãºã 0 ã«ã§ããã¡ã¢ãªæ¶è²»ãç¡é§ã«å¢ãã¦ãã¾ãåé¡ãããã¾ããã
```C++
#include
struct Empty {};
struct X
{
int i;
Empty e;
};
int main()
{
std::cout << sizeof(X) << '\n'; // 4 ãã大ãã
}
```
ãããåé¿ããããã«ã空ã®åºåºã¯ã©ã¹ã¯æé©åã«ãã£ã¦ãµã¤ãº 0 ã«ãã¦ãããã¨ãã仿§ãå©ç¨ãã Empty Base Optimization (EBO) ã¨ãããã¯ããã¯ããããæ¨æºã©ã¤ãã©ãªã§ãã`std::unique_ptr` ã `std::shared_ptr`, `std::vector` ãªã©ã«ä½¿ããã¦ãã¾ãã
```C++
#include
struct Empty {};
struct X : public Empty
{
int i;
};
int main()
{
std::cout << sizeof(X) << '\n'; // 4
}
```
ãããããããã®ã¯ã©ã¹ã§ç¶æ¿ã«ãã EBO ãå®è£
ããã¨ã³ã¼ããè¤éã«ãªãã¨ããæ¬ ç¹ãããã¾ãããC++20 ã§ã¯ã¡ã³ãã®å®£è¨ã« `[[no_unique_address]]` 屿§ãä»ãããã¨ã§ãç¶æ¿ã使ããªãã¦ãã³ã³ãã¤ã©ã EBO ã¨åããããªæé©åãã§ããããã«ãªãã徿¥ã®ç¶æ¿ã«ãã EBO ã使ã£ã¦ããã³ã¼ãããããåç´ãªã³ã¼ãã«ç½®ãæãããã¾ãã
```C++
#include
struct Empty {};
struct X
{
int i;
[[no_unique_address]] Empty e;
};
int main()
{
std::cout << sizeof(X) << '\n'; // 4
}
```
### ååã§ãããã¨ãæãããªæèã§ `typename` ãçç¥å¯è½ã« [(P0634R3)](https://wg21.link/P0634R3)
C++17 ã§ä¾ååãåã§ããå ´åã« `typename` ãä»ããªãã®ã¯ãæ´¾çã¯ã©ã¹å®ç¾©æã®åºåºã¯ã©ã¹ã®æå®ã¨ãåæååãªã¹ãã§ã®åºåºã¯ã©ã¹ã®æå®ã®ã¿ã§ããï¼å³å¯ã«ã¯ãã® 2 ã¤ã«ã¯ `typename` ãä»ãããã¾ããï¼ãC++20 ã§ã¯ãååãã使ããªãããã«ããã¤ãã®æèã§ `typename` ãçç¥å¯è½ã«ãªãã¾ããæ¬¡ã®ãµã³ãã«ã³ã¼ãã®å·¦å³ã¿ãã§æ¯è¼ã§ãã¾ãã
=== "C++17"
```C++
#include
#include
template
struct S : T::value_type // æ´¾çã¯ã©ã¹å®ç¾©æã®åºåºã¯ã©ã¹ã®æå®
{
using value_type = typename T::value_type;
S()
: T::value_type() {} // åæååãªã¹ãã§ã®åºåºã¯ã©ã¹ã®æå®
typename T::size_type max_size() const;
auto data()->typename T::pointer;
auto min_size() const
{
return static_cast(0);
}
};
template typename T::size_type MaxSize();
int main()
{
S<:vector>> s;
}
```
=== "C++20"
```C++
#include
#include
template // OK
struct S : T::value_type // æ´¾çã¯ã©ã¹å®ç¾©æã®åºåºã¯ã©ã¹ã®æå®
{
using value_type = T::value_type; // OK
S()
: T::value_type() {} // åæååãªã¹ãã§ã®åºåºã¯ã©ã¹ã®æå®
T::size_type max_size() const; // OK
auto data()->T::pointer; // OK
auto min_size() const
{
return static_cast<:size_type>(0); // OK
}
};
template T::size_type MaxSize(); // OK
int main()
{
S<:vector>> s;
}
```
### 宿°å¼ã§ã®ä»®æ³é¢æ°å¼ã³åºããå¯è½ã« [(P1064R0)](https://wg21.link/P1064)
ã³ã³ãã¤ã«æã«æ±ºå®å¯è½ã§ããã°ãåç
§ããã¤ã³ã¿ãéããä»®æ³é¢æ°ã®å¼ã³åºãã `constexpr` ã«ã§ããããã«ãªãã¾ãã`constexpr` 修飾ãããä»®æ³é¢æ°ãé `constexpr` 颿°ã§ãªã¼ãã¼ã©ã¤ããããã¨ãããã®éãå¯è½ã§ãã
```C++
struct Cpp
{
virtual int version() const = 0;
};
struct Cpp17 : Cpp
{
constexpr int version() const override
{
return 17;
}
};
struct Cpp20 : Cpp
{
constexpr int version() const override
{
return 20;
}
};
constexpr int GetVersion(const Cpp& a)
{
return a.version();
}
int main()
{
constexpr Cpp17 cpp17;
constexpr Cpp20 cpp20;
static_assert(GetVersion(cpp17) == 17);
static_assert(GetVersion(cpp20) == 20);
}
```
### `type_id` 㨠`dynamic_cast` ã constexpr ã« [(P1327R1)](https://wg21.link/P1327)
`dynamic_cast` 㨠`type_id` ããä¾å¤ãæããã±ã¼ã¹ãé¤ã㦠`constexpr` ã«ãªãã¾ãã
```C++
#include
struct Cpp
{
virtual int version() const = 0;
};
struct Cpp17 : Cpp
{
constexpr int version() const override
{
return 17;
}
};
struct Cpp20 : Cpp
{
constexpr int version() const override
{
return 20;
}
};
int main()
{
constexpr static Cpp17 cpp17;
constexpr const Cpp* pCpp = &cpp17;
constexpr auto& cpptype = typeid(*pCpp);
constexpr const Cpp& refCpp = cpp17;
constexpr const Cpp17& redCpp2 = dynamic_cast(refCpp);
}
```
次ã®ããã«ä¾å¤ãæããã±ã¼ã¹ã§ã¯ `constexpr` ã«ã§ããã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªãã¾ãã
```C++
#include
struct Cpp
{
virtual int version() const = 0;
};
struct Cpp17 : Cpp
{
constexpr int version() const override
{
return 17;
}
};
struct Cpp20 : Cpp
{
constexpr int version() const override
{
return 20;
}
};
int main()
{
constexpr Cpp* pCpp = nullptr;
constexpr auto& cpptype = typeid(*pCpp); //ã³ã³ãã¤ã«ã¨ã©ã¼: ä¾å¤ std::bad_typeid ãæãããã constexpr ä¸å¯
constexpr static Cpp17 cpp17;
constexpr const Cpp& refCpp = cpp17;
constexpr const Cpp20& redCpp2 = dynamic_cast(refCpp); // ã³ã³ãã¤ã«ã¨ã©ã¼: ä¾å¤ std::bad_cast ãæãããã constexpr ä¸å¯
}
```
### 宿°å¼ã«ããã¦å
±ç¨ä½ã®ã¢ã¯ãã£ãã¡ã³ãã®åãæ¿ããå¯è½ã« [(P1330R0)](https://wg21.link/P1330)
å
±ç¨ä½ã®ã¢ã¯ãã£ãã¡ã³ãã¨ã¯ãæå¾ã«åæåã¾ãã¯å¤ã代å
¥ããã¡ã³ãã®ãã¨ã§ããC++17 ã§ã¯å
±ç¨ä½ã®åæåãã¢ã¯ãã£ãã¡ã³ãã¸ã®ã¢ã¯ã»ã¹ã宿°å¼ã§è¡ãã¾ããããã¢ã¯ãã£ãã¡ã³ãã®åãæ¿ãã¯ã§ãã¾ããã§ããã宿°å¼ã§ã®ã¢ã¯ãã£ãã¡ã³ãã®åãæ¿ããå¯è½ã«ãªãã¨ãå
±ç¨ä½ã«ãã£ã¦å®è£
ããã `std::string` ã `std::optional` ãªã©ã®æ¨æºã©ã¤ãã©ãªã¯ã©ã¹ã®ã¡ã³ã颿°ã® `constexpr` 対å¿ãæ¡å
ã§ãã¾ããéã¢ã¯ãã£ãã¡ã³ãã¸ã®ã¢ã¯ã»ã¹ã¯æªå®ç¾©åä½ãªã®ã§ã宿°å¼ã§è¡ãã¨ã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªãã¾ãã
```C++
#include
union Value
{
float f;
std::uint32_t i;
};
constexpr Value GetFloat(float x)
{
return Value{ x }; // value.f ãã¢ã¯ãã£ãã¡ã³ã
}
constexpr Value GetUint(std::uint32_t x)
{
Value value = GetFloat(0.0f); // value.f ãã¢ã¯ãã£ãã¡ã³ã
value.i = x; // value.i ãã¢ã¯ãã£ãã¡ã³ãã«
return value;
}
int main()
{
static_assert(GetUint(123).i == 123);
}
```
### 宿°å¼ã®æèã§ã¯ `try-catch` ãç¡è¦ããããã« [(P1002R1)](https://wg21.link/P1002)
ããã¾ã§ `constexpr` 颿°ã®ä¸ã«ã¯ `try-catch` ãããã¯ãæ¸ããã¨ãã§ãã¾ããã§ããããããã`std::vector` çã®ã³ã³ããã `constexpr` 対å¿ããã«ããã£ã¦ã¯ããã®å¶éãéå£ã¨ãªããããC++20 ã§ã¯ `constexpr` 颿°ã®ä¸ã® `try-catch` ã¯ã宿°å¼ã¨ãã¦è©ä¾¡ãããã¨ãã«ã¯ç¡è¦ãããã仿§ãæ¹ãããã¾ãã宿°å¼ã®è©ä¾¡ä¸ã«ä¾å¤ãæããããã§ããã°ã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªãã¾ãã`std::vector` ãªã©ã `constexpr` 対å¿ãããããã®æªç½®ã§ãããå°æ¥ã® C++ ã«ãããã³ã³ãã¤ã«æä¾å¤å¦çã®å®ç¾ãå¦å®ãããã®ã§ã¯ããã¾ããã
```cpp
#include
#include
#include
constexpr std::uint32_t AddU8(std::uint32_t a, std::uint32_t b)
{
if ((a + b) >= 256)
{
throw std::exception{};
}
return a + b;
}
constexpr std::uint32_t DoubleU8(std::uint32_t n)
{
try
{
return AddU8(n, n);
}
catch (const std::exception& except)
{
return 0;
}
}
int main()
{
static_assert(DoubleU8(123) == 246); // OK: ä¾å¤ãæããã«å®æ°å¼ã¨ãã¦è©ä¾¡å¯è½
//static_assert(DoubleU8(200) > 0); // ã³ã³ãã¤ã«ã¨ã©ã¼: 宿°å¼ã¨ãã¦è©ä¾¡ããã constexpr 颿°å
ã§ä¾å¤ãæãããã
std::cout << "result: " << DoubleU8(200) << '\n'; // OK: å®è¡æã«è©ä¾¡ããã颿°ã§ä¾å¤ãçºçãã
}
```
### æ·»åå¼ã«ãããã³ã³ãæ¼ç®åã®ä½¿ç¨ã deprecated ã« [(P1161R3)](https://wg21.link/P1161R3)
ããã¾ã§ `array[x, y]` ã¨ããã³ã¼ãã§ã¯ãã³ã³ãæ¼ç®åã®ä½ç¨ã§ `y` ãæ·»åæ¼ç®ã®å¼æ°ã¨ãã¦æ¸¡ããã¾ããããããããã®æåã¯ç´ãããããå°æ¥ã® C++ æ¨æºã©ã¤ãã©ãªã«å¤æ¬¡å
é
åã¯ã©ã¹ãå®è£
ãããã¨ããæ·»åæ¼ç®åãè¤æ°ã®å¼æ°ã«å¯¾å¿ããããããªè¦æ ¼ã追å ããããã§ã®éå£ã«ããªãã¾ãããã®ãããC++20 ããã`array[(x, y)]` ã®ããã«æ¬å¼§ã使ç¨ããå ´åãã®ãããæ·»åå¼ã«ãããã³ã³ãæ¼ç®åã®ä½¿ç¨ã deprecated ã«ãªãã¾ããå¤ãã³ã¼ãã§ deprecated ãªæ¸ãæ¹ããã¦ããå ´åãåè¿°ã®ããã« `()` ãä»ãããã¨ã§ãã³ã¼ãã®æåã«å½±é¿ãä¸ããã«ç§»æ¤ãå¯è½ã§ãã
```C++
#include
int main()
{
std::vector v(10);
int index = 0;
v[++index, 0] = -1; // C++17 ã¾ã§ OK, C++20 ãã deprecated
v[(++index, 0)] = -1; // OK
}
```
### ã¹ã³ã¼ãä»ãåæåã«å¯¾ãã using 宣è¨ãã§ããããã« [(P1099R5)](http://wg21.link/p1099r5)
ããã¾ã§ã¯ãenum class ã®ã¹ã³ã¼ã解決ãçç¥ããæ¹æ³ãç¡ããæ¬¡ã®ãã㪠`switch` ã§ãåæåã®ååãä½åº¦ãç»å ´ãããããªã³ã¼ããæ¸ãå¿
è¦ããããèªã¿ã«ãããé·ãåæåã®ååãé¿ããããåå ã«ãªã£ã¦ãã¾ããã
```C++
#include
#include
enum class Terrain
{
Open, Mountain, River, Ocean
};
constexpr std::string_view ToString(Terrain terrain)
{
using namespace std::string_view_literals;
switch (terrain)
{
case Terrain::Open: return "Open"sv;
case Terrain::Mountain: return "Mountain"sv;
case Terrain::River: return "River"sv;
case Terrain::Ocean: return "Ocean"sv;
default: return ""sv;
}
}
int main()
{
std::cout << ToString(Terrain::Mountain);
}
```
C++20 ã§ã¯ `using` 宣è¨ãæ¡å¼µãã`using Terrain::Open;` ã§ `Open` ãã¨ã¤ãªã¢ã¹ã¨ãã¦ä½¿ããããã«ãªãã¾ããã¾ã `using enum` 宣è¨ã¨ããæ°ããä»çµã¿ã«ããã`using enum Terrain;` ã§ `Terrain` ããã¼ã«ã«ã¹ã³ã¼ãã«å°å
¥ãããã¹ã³ã¼ã解決æ¼ç®åã使ããã«ãã®åæåã使ããããã«ãªãã¾ãã
```C++
enum class Terrain
{
Open, Mountain, River, Ocean
};
constexpr std::string_view ToString(Terrain terrain)
{
using namespace std::string_view_literals;
switch (terrain)
{
using enum Terrain; // using enum 宣è¨ã§ãåæåã®åå Terrain ããã¼ã«ã«ã¹ã³ã¼ãã«å°å
¥
case Open: return "Open"sv;
case Mountain: return "Mountain"sv;
case River: return "River"sv;
case Ocean: return "Ocean"sv;
default: return ""sv;
}
}
int main()
{
using Terrain::Mountain; // using 宣è¨ã§ãåæå Mountain ããã¼ã«ã«ã¹ã³ã¼ãã«å°å
¥
std::cout << ToString(Mountain);
}
```
ãªããæ¬¡ã®ããã«è¤æ°ã® `using` 宣è¨ã«ãã£ã¦ååã®è¡çªãèµ·ããå ´åã¯ã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªãã¾ãã
```C++
#include
#include
enum class Terrain
{
Open, Mountain, River, Ocean
};
enum class State
{
Open, Closed
};
int main()
{
using enum Terrain; // OK
using enum State; // ã³ã³ãã¤ã«ã¨ã©ã¼: Terrain::Open 㨠State::Open ã®ååãè¡çª
}
```
### ã³ã³ã¹ãã©ã¯ã¿ã« `[[nodiscard]]` ã使ããããã« [(P1771R1)](http://wg21.link/p1771r1)
C++17 ã§ `[[nodiscard]]` ãå°å
¥ãããéã仿§ã§ã¯ã³ã³ã¹ãã©ã¯ã¿ã対象ã¨ãã¦ãã¾ããã§ããï¼ãã ããGCC ã§ã¯è¦åãåºãã¤ã¤ãã³ã³ã¹ãã©ã¯ã¿ã«ä»ãã `[[nodiscard]]` ããã§ãã¯ãã¦ãã¾ããï¼ãã³ã³ã¹ãã©ã¯ã¿ã®å¼ã³åºãã«ãã£ã¦ä½æããã䏿ãªãã¸ã§ã¯ããæå³ããç¡è¦ãããã¨ãã«è¦åãåºããã¨ãã¦ã¼ã¶ã®ééããæ¸ããã¾ããããã§ãã³ã³ã¹ãã©ã¯ã¿ã«ã `[[nodiscard]]` 屿§ãä»ãããããããC++17 åãã®è¦æ ¼ã«ããã®ã¼ã£ã¦ä»æ§ãä¿®æ£ãããC++20 ããã³ããã®å¤æ´ã«å¯¾å¿ãã C++17 ã³ã³ãã¤ã©ã§æ°ä»æ§ãå©ç¨ã§ããããã«ãªãã¾ãããªãããã¹ãã©ã¯ã¿ãå®ç¾©ãã¦ããå ´åã§ãè¦åã¯æ¶ãã¾ããã
```C++
struct Circle
{
double x, y, r;
Circle() = default;
[[nodiscard]] constexpr Circle(double _x, double _y, double _r) noexcept
: x(_x), y(_y), r(_r) {}
void draw() const { /* ... */ }
};
int main()
{
Circle(200, 300, 50); // warning: nodiscard 屿§ã®ã³ã³ã¹ãã©ã¯ã¿ã§ä½æããã䏿ãªãã¸ã§ã¯ããç¡è¦
Circle(400, 300, 50).draw();
}
```
### ãã¹ãããåå空éå®ç¾©ã§ `inline namespace` ã使ããããã« [(P1094R2)](http://wg21.link/p1094r2)
C++17 ã§ãã¹ãããåå空éå®ç¾©ãå°å
¥ããã¾ãããããã®ä¸ã§ã¯ `inline namespace` ã使ããã¨ãã§ããã`inline namespace` ã `namespace` å
ã«ããæ¬¡ã®ãããªã±ã¼ã¹ã§æ©æµãåãããã¾ããã§ãããC++20 ããã¯ãã¹ãããåå空éå®ç¾©ã®ä¸ã§ `inline` ã使ããããã«ãªãã¾ãã
=== "C++17"
```C++
#include
namespace mylib::v1::util
{
constexpr int GetValue() { return 1; }
}
namespace mylib
{
inline namespace v2
{
namespace util
{
constexpr int GetValue() { return 2; }
}
}
}
int main()
{
std::cout << mylib::v1::util::GetValue() << '\n';
std::cout << mylib::v2::util::GetValue() << '\n';
std::cout << mylib::util::GetValue() << '\n'; // v2
}
```
=== "C++20"
```C++
#include
namespace mylib::v1::util
{
constexpr int GetValue() { return 1; }
}
namespace mylib::inline v2::util
{
constexpr int GetValue() { return 2; }
}
int main()
{
std::cout << mylib::v1::util::GetValue() << '\n';
std::cout << mylib::v2::util::GetValue() << '\n';
std::cout << mylib::util::GetValue() << '\n'; // v2
}
```
### æ¬æ¥ã¢ã¯ã»ã¹å¯è½ãª private ã¡ã³ãã«æ§é åæç¸ã§ã¯ã¢ã¯ã»ã¹ã§ããªãã£ã仿§ãä¿®æ£ [(P0969R0)](https://wg21.link/P0969R0)
ã¡ã³ã颿°å
ã§èªèº«ã® `private` ã¡ã³ãã«ã¢ã¯ã»ã¹ãããã¨ãã`friend` æå®ããã颿°ã§è©²å½ã¯ã©ã¹ã® `private` ã¡ã³ã夿°ã«ã¢ã¯ã»ã¹ãããã¨ã¯é常å¯è½ã§ãããC++17 ã®æ§é åæç¸ã¯ã¯ã©ã¹ã® `public` ã¡ã³ãã«ãããã¤ã³ãã§ããªãã¨ããè¦æ ¼æé¢ã®å¶ç´ããããæ¬¡ã®ãããªã±ã¼ã¹ã§ä¸è²«æ§ãããã¾ããã§ããããã®å¶ç´ã課ãåççãªçç±ã¯ç¡ãã£ããããC++17 åãã®è¦æ ¼ã«ããã®ã¼ã£ã¦ä»æ§ãä¿®æ£ãããã¢ã¯ã»ã¹å¯è½ã§ããã° `private` ã¡ã³ã夿°ããã¤ã³ãã§ããããã«ãªãã¾ããC++20 ããã³ããã®å¤æ´ã«å¯¾å¿ãã C++17 ã³ã³ãã¤ã©ã§æ°ä»æ§ãå©ç¨ã§ãã¾ãã
```C++
class Date
{
private:
int m_year, m_month, m_day;
public:
friend void Work(const Date& date);
void f(const Date& other) const
{
// OK
int year = other.m_year;
int month = other.m_month;
int day = other.m_day;
// ããã¾ã§ã¯ã³ã³ãã¤ã«ã¨ã©ã¼, C++20 以é OK
auto [y, m, d] = other;
}
};
// friend æå®ããã¦ãã颿°
void Work(const Date& date)
{
// OK
int year = date.m_year;
int month = date.m_month;
int day = date.m_day;
// ããã¾ã§ã¯ã³ã³ãã¤ã«ã¨ã©ã¼, C++20 以é OK
auto [y, m, d] = date;
}
int main()
{
}
```
### ã¦ã¼ã¶å®£è¨ãããã³ã³ã¹ãã©ã¯ã¿ãæã¤ã¯ã©ã¹ã®éæä½åæåãç¦æ¢ [(P1008R1)](https://wg21.link/P1008R1)
C++17 ã¾ã§ã¯éæä½ã®è¦ä»¶ãç·©ãã£ããããã³ã³ã¹ãã©ã¯ã¿ã«ã¤ãã¦ã¯ãããã©ã«ãã³ã³ã¹ãã©ã¯ã¿ã `= delete` ã¾ã㯠`private` ã§ãã£ã¦ããéæä½åæåã«ãã£ã¦åæåã§ããæãéãããã¾ãããããã¯ã¡ã³ã夿°ãæå³ããªãå¤ã§åæåãããã¨ãã£ãåé¡ãå¼ãèµ·ããã¾ããC++20 ããã¯éæä½ã®è¦ä»¶ãå³ãããªããã¦ã¼ã¶å®£è¨ãããã³ã³ã¹ãã©ã¯ã¿ãããã¯ã©ã¹ã¯éæä½ã«ã¯ãªãã¾ããã
```C++
struct A
{
A() = delete;
};
struct B
{
private:
B() = default;
};
struct C
{
int i = 0;
C() = default;
};
int main()
{
A a1; // ã³ã³ãã¤ã«ã¨ã©ã¼
A a2{}; // C++17 ã¾ã§ã¯ OK, C++20 ããã¯ã³ã³ãã¤ã«ã¨ã©ã¼
B b1; // ã³ã³ãã¤ã«ã¨ã©ã¼
B b2{}; // C++17 ã¾ã§ã¯ OK, C++20 ããã¯ã³ã³ãã¤ã«ã¨ã©ã¼
C c1(123); //ã³ã³ãã¤ã«ã¨ã©ã¼
C c2{ 123 }; // C++17 ã¾ã§ã¯ OK, C++20 ããã¯ã³ã³ãã¤ã«ã¨ã©ã¼
}
```
### `throw()` ã«ããåçä¾å¤æå®ãåé¤ [(P0619R4)](https://wg21.link/P0619R4)
C++11 ã§ã¯ã`noexcept` ã®è¿½å ã«åããã`throw(typeid, ...)` ã `throw()` ã«ããåçä¾å¤æå®ã鿍奍åããã¾ãããC++17 ã§ã¯åè
ãåé¤ããã¾ããããå¤ãã³ã¼ãã«ããã¦åºã使ããã¦ããå¾è
ã¯ãç§»è¡ç¶äºã®ããã« `noexcept(true)` ã®ã¨ã¤ãªã¢ã¹ã¨ãã¦æ¹ãããã¤ã¤ä¿æããã¦ãã¾ãããC++20 ã§ã¯å¾è
ãåé¤ããã¾ãã
### ã¡ãã»ã¼ã¸ä»ãã® `[[nodiscard]]` 屿§ [(P1301R4)](https://wg21.link/P1301R4)
C++17 ã§è¿½å ããã `[[nodiscard]]` 屿§ã¯ãã©ã¤ãã©ãªãªã©ãæä¾ãã颿°ã®èª¤ç¨ãé²ãå©ãã«ãªãã¾ããã颿°ããªã `[[nodiscard]]` 屿§ãæã£ã¦ããã®ãã«ã¤ãã¦ãå©ç¨è
ã«ååãªæ
å ±ãä¼ãããªãå ´åãããã¾ãããC++20 ã§ã¯ `[[nodiscard("....")]]` ã®ãããªå½¢å¼ã§ã¡ãã»ã¼ã¸ã追å ã§ããããã«ãªãã¾ããæ»ãå¤ã®ç¡è¦ããã£ãå ´åãã³ã³ãã¤ã©ã¯è¦åã«å ãã¦ãã®ã¡ãã»ã¼ã¸ãè£è¶³æ
å ±ã¨ãã¦åºåã§ãã¾ãã
```C++
#include
struct Data
{
private:
std::vector m_data;
public:
void clear()
{
m_data.clear();
}
[[nodiscard("Did you mean 'clear'?")]]
bool empty() const
{
return m_data.empty();
}
};
int main()
{
Data data;
data.empty();
}
```
ã³ã³ãã¤ã©ã®åºåä¾
```
prog.cc:27:2: warning: ignoring return value of function declared with 'nodiscard' attribute:
Did you mean 'clear'? [-Wunused-result]
data.empty();
^~~~~~~~~~
1 warning generated.
```
### æç¤ºä»ãåæååã«ããéæä½ã®åæå [(P0329R4)](https://wg21.link/P0329R4)
C++20 ãããéæä½ã«ããã¦ãã¡ã³ã夿°åãæå®ããåæåï¼æç¤ºä»ãåæååãç¨ããåæå: "Designated Initialization" ï¼ãã§ããããã«ãªãã¾ããC è¨èª (C99) ã«ãåæ§ã®æ©è½ãããã¾ãããC++20 ã§ã¯ C99 ã®æç¤ºä»ãåæååã¨æ¯è¼ãã¦ä»¥ä¸ã®ãããªå¶ç´ã追å ããã¦ãã¾ãã
- (a) æç¤ºåã®é çªã¯ã¡ã³ãã®å®£è¨é ã¨åãã§ããå¿
è¦ããã
- (b) æç¤ºä»ãåæååã¨é常ã®åæååã®æ··å¨ã¯ã§ããªã
- (c) åä¸ã¡ã³ãã®æç¤ºä»ãåæååã¯è¤æ°å使ããªã
- (d) æç¤ºä»ãåæååã¯ãã¹ãã§ããªã
- (e) é
åã®æç¤ºä»ãåæåã¯ã§ããªã
ã¾ããåæååã®è©ä¾¡é åºãå·¦ããå³ã§ãããã¨ãä¿è¨¼ããã¾ãã
```C++
#include
struct Point
{
int x, y;
};
struct Item
{
std::string name;
int id = -1;
Point pos = { -1, -1 };
};
void F(Point) {}
int main()
{
Point p1 = { .x = 10, .y = 20 }; // OK
Point p2{ .x = 10, .y = 20 }; // OK
Point p3 = { .x = 10 }; // OK: y 㯠0 ã«åæåããã
Point p4 = { .y = 20 }; // OK: x 㯠0 ã«åæåããã
F({ .x = 10, .y = 20 }); // OK
Point p4 = { .y = 20, .x = 30 }; // ã³ã³ãã¤ã«ã¨ã©ã¼: (a) æç¤ºåã®é çªãã¡ã³ãã®å®£è¨é ã¨ç°ãªã
Point p5 = { .x = 20, 40 }; // ã³ã³ãã¤ã«ã¨ã©ã¼: (b) æç¤ºä»ãåæååã¨é常ã®åæååã¯æ··å¨ã§ããªã
Point p6 = { .x = 20, .x = 30, .y = 30 }; // ã³ã³ãã¤ã«ã¨ã©ã¼: (c) åä¸ã¡ã³ãã®æç¤ºä»ãåæååã¯è¤æ°åç»å ´ã§ããªã
Item i1{ .name = "shield", .id = 30, .pos = { 5, 2 } }; // OK
Item i2{ .id = 0 }; // OK: name 㯠{} ã§åæåãpos 㯠{ -1, -1 } ã§åæå
Item i3{ .pos.x = 10, .pos.y = 40 }; // ã³ã³ãã¤ã«ã¨ã©ã¼: (d) æç¤ºä»ãåæååã¯ãã¹ãã§ããªã
int arr[3] = { [1] = 5 }; // ã³ã³ãã¤ã«ã¨ã©ã¼: (e) é
åã®æç¤ºä»ãåæåã¯ã§ããªã
}
```
徿¥ã¾ã§ã® `Point p{}`, `Item i{}` ã®ãããªéæä½åæåããæç¤ºä»ãåæååã 0 åã®åæåãã¨èããã¨ãæ°ããæåãçè§£ãããããªãã¾ãããªããæ¬¡ã®ããã«éæä½ã§ã¯ãªãã¯ã©ã¹ã®åæåã«ã¯ãæç¤ºä»ãåæååã¯ä½¿ãã¾ããã
```C++
#include
struct Point
{
int x, y;
Point() = default;
Point(int _x, int _y)
: x(_x)
, y(_y) {}
};
int main()
{
// ã³ã³ãã¤ã«ã¨ã©ã¼:
// ã¦ã¼ã¶å®£è¨ãããã³ã³ã¹ãã©ã¯ã¿ãæã¤ããéæä½ã§ã¯ãªã
// éæä½ã§ãªãããæç¤ºä»ãåæååã使ããªã
Point p{ .x = 20, .y = 4 };
}
```
## æ¨æºã©ã¤ãã©ãª
### æååã®å
é ãæ«å°¾ããããæååã¨ä¸è´ãããå¤å® [(P0457R2)](https://wg21.link/P0457R2)
`std::basic_string` 㨠`std::basic_string_view` ã«ã`starts_with()` 㨠`ends_with()` ã¡ã³ã颿°ã追å ããã¾ãã
```C++
#include
#include
constexpr bool HasPNGExtension(std::string_view filePath)
{
// æååã ".png" ã§çµãããªã true, ãã以å¤ã¯ false ãè¿ã
return filePath.ends_with(".png");
}
int main()
{
std::cout << std::boolalpha;
std::cout << HasPNGExtension("picture.png") << '\n';
std::cout << HasPNGExtension("photo.jpg") << '\n';
std::cout << HasPNGExtension("music.mp3") << '\n';
}
```
```
true
false
false
```
### `operator>>(basic_istream&, charT*)` ã®ç¬¬äºå¼æ°ã `charT(&)[N]` ã«å¤æ´ãã¦å®å
¨ã« [(P0487R1)](https://wg21.link/P0487R1)
C++17 ã¾ã§ã® `operator>>(basic_istream&, charT*)` ã¯ã颿°ã«ãããã¡ã®ãµã¤ãºã渡ãããªããããæ¬¡ã®ãããªããã°ã©ã ã§ãããã¡ãªã¼ãã¼ããã¼ã¸ã®å¯¾çãå¿
è¦ã§ããã
```C++
#include
#include
int main()
{
char buffer[4];
// std::cin >> buffer; // å±éº: ãããã¡ãªã¼ãã¼ããã¼ã®å¯è½æ§
std::cin >> std::setw(4) >> buffer; // OK: ãããã¡ãªã¼ãã¼ããã¼å¯¾ç
std::cout << buffer;
}
```
C++20 ã§ã¯å¼æ°ã次ã®ããã«å¤æ´ãã颿°ããããã¡ãªã¼ãã¼ããã¼ã®å¯¾çãå®è£
ããããã«ãªãã¾ãã
```C++
// C++17 ã¾ã§
template
basic_istream& operator>>(basic_istream& in, charT* s);
// C++20 ãã
template
basic_istream& operator>>(basic_istream& in, charT (&s)[N]);
```
```C++
#include
#include
int main()
{
char buffer[4];
std::cin >> buffer; // OK: C++20 ã§ã¯ãããã¡ãªã¼ãã¼ããã¼ãé²ãã
std::cout << buffer;
}
```
ãã®å¤æ´ã«ä¼´ããC++17 ã¾ã§ã¯æå¹ã ã£ã次ã®ãããªããã°ã©ã ããC++20 ããã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªãã¾ãã
```C++
#include
#include
int main()
{
char* p = new char[100];
std::cin >> std::setw(100) >> p; // C++20 ããã¯ã³ã³ãã¤ã«ã¨ã©ã¼
std::cout << p;
}
```
### æ»ãå¤ã®ç¡è¦ãä¸å
·åããããã颿°ã« `[[nodiscard]]` ãä»ä¸ [(P0600R1)](https://wg21.link/P0600R1)
C++17 ã§å°å
¥ããã `[[nodiscard]]` 屿§ãæ¨æºã©ã¤ãã©ãªã§æ´»ç¨ããããã«ãªãã¾ããC++20 ã§ã¯ä»ä¸åºæºããæ»ãå¤ã®ç¡è¦ããã©ãã«ãã¡ã¢ãªãªã¼ã¯ãªã©ã®é大ãªã¨ã©ã¼ãå¼ãèµ·ãã C++ ã®é¢æ°ãã¨ãã`async()`, `launder()`, `allocate()`, `empty()`, `operator new()` ã対象ã¨ãªã£ã¦ãã¾ãã
```C++
#include
#include
int main()
{
std::vector v = { 10, 20, 30 };
v.empty(); // C++20 ã§ã¯è¦å
std::async(std::launch::async, [] { return 1; }); // C++20 ã§ã¯è¦å
}
```
MSVC ã®æ¨æºã©ã¤ãã©ãªã§ã¯ Visual Studio 2017 15.6 以éãè¦æ ¼ã®ç¯å²ãè¶
ãã¦ããå¤ãã®é¢æ°ï¼[2,500 å以ä¸](https://devblogs.microsoft.com/cppblog/c17-progress-in-vs-2017-15-5-and-15-6/)ï¼ã« `[[nodiscard]]` 屿§ã使ã£ã¦ãã¾ãããã®çµæã[Chromium ã®ã½ã¼ã¹ã«ç¡æå³ãª std::move() ãè¦ã¤ãã](https://bugs.chromium.org/p/webrtc/issues/detail?id=8463)ãªã©ãæ¢åã®ã³ã¼ããã¼ã¹ã®ãã°ã®çºè¦ã«å½¹ç«ã£ã¦ãã¾ãã
### `` ãããã®ãã¹ã¦ã®é¢æ°ã constexpr ã« [(P1023R0)](https://wg21.link/P1023R0), [(P1032R1)](https://wg21.link/P1032R1)
C++17 ã® `` ãããã§ã¯ãæ¯è¼æ¼ç®åã`swap()`, `fill()` 以å¤ã®ãã¹ã¦ã®é¢æ°ã constexpr ã§ãããC++20 ã§ã¯ããã«ãarray ã®æ¯è¼æ¼ç®ã®å®è£
ã«ä½¿ããã¦ãã `std::equal()` 㨠`std::lexicographical_compare()` ã [constexpr ã«ãªã£ã (P0202R3)](https://wg21.link/P0202R3) ãã¨ã«ã¨ããªããarray ã®æ¯è¼æ¼ç®åã constexpr ã¨ããã¾ã `swap()` 㨠`fill()` ã«ã¤ãã¦ã constexpr ã«ãããã¨ã決ããarray ãããã®ãã¹ã¦ã®é¢æ°ã constexpr ã§æä¾ããã¾ãã
### `` ãããã® `zero()`, `min()`, `max()` 颿°ã noexcept ã« [(P0972R0)](https://wg21.link/P0972R0)
`std::chrono::duration_values`, `std::chrono::duration`, `std::chrono::time_point` ãªã©ã® `zero()`, `min()`, `max()` 颿°ã« noexcept ãä»ãã¾ãã
### `pointer_traits` ã constexpr ã« [(P1006R1)](https://wg21.link/P1006R1)
`std::vector` ã constexpr ã«ããã®ã«å¿
è¦ãªããã`std::pointer_traits::pointer_to()` 颿°ã constrexpr ã«ãªãã¾ãã
### ãã¤ã³ã¿ã®ã¢ã©ã¤ã¡ã³ããæé©åãã³ãã¨ãã¦ã³ã³ãã¤ã©ã«ä¼ãã `assume_aligned()` 颿° [(P1007R3)](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1007r3.pdf)
ãã¼ã¿ã®ã¢ãã¬ã¹ã 16 ãã¤ããªã©ã®ãµã¤ãºã«ã¢ã©ã¤ã¡ã³ãããã¦ããå ´åãã³ã³ãã¤ã©ã SIMD ã使ã£ãæé©ãªã³ã¼ããçæã§ããå¯è½æ§ãããã¾ãããããã¤ã³ã¿ã®æããã¼ã¿ãã¢ã©ã¤ã¡ã³ãããã¦ãããã¨ãã³ã³ãã¤ã©ã«ä¼ããæ¹æ³ã¨ãã¦ãGCC ã Clang ã§ã¯ `__builtin_assume_aligned()` ã `__attribute__((assume_aligned(alignment)))`, ICC ã§ã¯ `__assume_aligned()` ãªã©ã®ç¬èªæ¡å¼µãããã¾ãããæ¨æºåãããæ¹æ³ã¯ããã¾ããã§ãããC++20 ã§ã¯ããããã®å·®ç°ãå¸åããæ¬¡ã®ãããªé¢æ°ãã³ãã¬ã¼ããæä¾ããã¾ãã
```C++
template
[[nodiscard]] constexpr T* assume_aligned(T* ptr);
```
å®éã«ã¯æ¬¡ã®ããã«ä½¿ãã¾ãã
```C++
void Multiply(float* x, size_t size, float factor)
{
float* ax = std::assume_aligned<64>(x); // x ã 64 ãã¤ãã¢ã©ã¤ã¡ã³ãã§ãããã¨ãä¼ãã
for (size_t i = 0; i < size; ++i) // ã«ã¼ããé©å®æé©åããã
{
ax[i] *= factor;
}
}
```
### ã¹ãã¼ããã¤ã³ã¿ã®ä½ææã«å¤ãããã©ã«ãåæåãã make 颿°ã追å [(P1020R1)](https://wg21.link/P1020R1), [(P1973R1)](https://wg21.link/P1973R1)
å®è¡ææ§è½ã®ããã«ã`float` ã `unsigned char` ãªã©çµã¿è¾¼ã¿åã®é
åã®å¤ãããã©ã«ãåæåããããï¼ã¼ãåæåããªãï¼ã±ã¼ã¹ãããã¾ãããããã`make_unique` ã `make_shared`, `allocate_shared` ã§ã¹ãã¼ããã¤ã³ã¿ã使ããå ´åã«ã¯å¤åæåãå®è¡ããã¾ããC++20 ã§ã¯ãå¤åæåãããã«ããã©ã«ãåæåã§ã¹ãã¼ããã¤ã³ã¿ã使ãã颿° `make_unique_for_overwrite`, `make_shared_for_overwrite`, `allocate_shared_for_overwrite` ã追å ããã¾ããã
```C++
#include
#include
// æªåæåã®å¤æ°ã使ãå®é¨çãªã³ã¼ã
int main()
{
float v[4]; // ããã©ã«ãåæå
for (int i = 0; i < 4; ++i)
{
std::cout << v[i] << '\n';
}
auto pv = std::make_unique(4); // å¤åæå (0 åæå)
for (int i = 0; i < 4; ++i)
{
std::cout << pv[i] << '\n';
}
auto pd = std::make_unique_for_overwrite(4); // ããã©ã«ãåæå
for (int i = 0; i < 4; ++i)
{
std::cout << pd[i] << '\n';
}
}
```
åºåä¾
```
2.20325e-38
4.11052e+32
1.3013e-45
2.48626e-38
0
0
0
0
2.30415e-38
2.51341e-38
4.63281e+30
2.32703e+17
```
### éé åºé£æ³ã³ã³ããã®ã«ãã¯ã¢ããæä½ã§ã`key_type` ã¨æ¯è¼å¯è½ãªåã夿ããã«ä½¿ããããã« [(P0919R3)](http://wg21.link/P0919r3), [(P1690R1)](http://wg21.link/P1690R1)
C++17 ã¾ã§ã® `unorderd_map` ã `unordered_set` ãªã©éé åºé£æ³ã³ã³ããã§ã¯ã`find()`, `count()`, `equal_range()` ãªã©ã«ãã¯ã¢ãããè¡ãã¡ã³ã颿°ã¯å¼æ°ã« `key_type` ãã¨ããä¾ãã°æ¬¡ã®ãããªã±ã¼ã¹ã§ `std::string` åã®ä¸æãªãã¸ã§ã¯ãã使ããã¦éå¹çã§ããã
```C++
#include
#include
int main()
{
std::unordered_map<:string int> table = { /* ... */ };
auto it = table.find("abc"); // std::string åã®ä¸æãªãã¸ã§ã¯ãã使ããã
}
```
C++20 ã§ã¯ãéé åºé£æ³ã³ã³ããã®ãã³ãã¬ã¼ããã©ã¡ã¼ã¿ã«ã¤ã㦠`Hash::is_transparent` 㨠`Pred::is_transparent` ãåå¨ããã¨ãã«ã`key_type` 以å¤ã®åã弿°ã«ã¨ãã¡ã³ã颿°ãã³ãã¬ã¼ãã®ãªã¼ãã¼ãã¼ãã使ç¨å¯è½ã«ãªãã䏿ãªãã¸ã§ã¯ãã®ä½æãåé¿ã§ããããã«ãªãã¾ãã
```C++
#include
#include
#include
struct string_compare
{
using is_transparent = void;
bool operator()(std::string_view key, std::string_view txt) const { return key == txt; }
};
struct string_hash
{
using is_transparent = void;
using transparent_key_equal = string_compare;
using hash_type = std::hash<:string_view>; // helper local type
size_t operator()(std::string_view txt) const { return hash_type{}(txt); }
size_t operator()(const std::string& txt) const { return hash_type{}(txt); }
size_t operator()(const char* txt) const { return hash_type{}(txt); }
};
int main()
{
using namespace std::literals;
std::unordered_map<:string int string_hash string_compare> table = { /* ... */ };
auto it1 = table.find("abc"); // std::string åã®ä¸æãªãã¸ã§ã¯ãã¯ä½æãããªã
auto it2 = table.find("abc"sv); // std::string åã®ä¸æãªãã¸ã§ã¯ãã¯ä½æãããªã
}
```
### 2 ã¤ã®å¤ã®ä¸ç¹ãè¨ç®ãã `std::midpoint()` 颿° [(P0811R3)](https://wg21.link/P0811R3)
2 ã¤ã®å¤ `a`, `b` ã®ä¸ç¹ãè¨ç®ããéã«ãåç´ãª `(a + b) / 2` ã¨ããå¼ã§ã¯ãªã¼ãã¼ããã¼ãèµ·ããå¯è½æ§ãããã¾ããC++20 ã§è¿½å ããã `std::midpoint()` 颿°ã§ã¯ãæ´æ°ã«å¯¾ãã¦
```C++
constexpr Integer midpoint(Integer a, Integer b) noexcept
{
using U = make_unsigned_t;
return a>b ? a-(U(a)-b)/2 : a+(U(b)-a)/2;
}
```
ã®ãããªå®è£
ã使ããããªã¼ãã¼ããã¼ãåé¿ã§ãã¾ãã`(a + b)` ã奿°ã«ãªãã±ã¼ã¹ã®çµæã¯ `a` ã®æ¹åã«ä¸¸ãããã¾ãã
æµ®åå°æ°ç¹æ°ã«å¯¾ãã¦ã¯æ¬¡ã®ãããªå®è£
ã使ããã¾ãã
```C++
Float midpoint(Float a, Float b)
{
return isnormal(a) && isnormal(b) ? a/2+b/2 : (a+b)/2;
}
```
```C++
#include
#include
int main()
{
std::cout << (2'000'000'000 + 1'000'000'000) / 2 << '\n'; // ãªã¼ãã¼ããã¼
std::cout << std::midpoint(2'000'000'000, 1'000'000'000) << '\n'; // 1500000000
std::cout << std::midpoint(1, 4) << '\n'; // 2
std::cout << std::midpoint(4, 1) << '\n'; // 3
}
```
### 2 ã¤ã®å¤ã®ç·å½¢è£éãè¨ç®ãã `std::lerp()` 颿° [(P0811R3)](https://wg21.link/P0811R3)
2 ç¹ `a`, `b` ã®éããã©ã¡ã¼ã¿ `t` ã«ãã£ã¦ç·å½¢è£éãã颿°ãæä¾ããã¾ããè¨ç®çµæ `r` 㯠`a + t * (b - a)` ã«ãã£ã¦æ±ãããã¾ãããå®è£
ã«ãã `isfinite(a) && isfinite(b)` ã®ã¨ã
- `lerp(a, b, 0) == a && lerp(a, b, 1) == b`
- `0 <= t && t <= 1` ã®ã¨ã `isfinite(r)`
- `isfinite(t) && a == b` ã®ã¨ã `r == a`
- `isfinite(t) || !isnan(t) && (b - a) != 0` ã®ã¨ã `!isnan(r)`
ã¾ãã`cmp(lerp(a,b,t2), lerp(a,b,t1)) * cmp(t2,t1) * cmp(b,a) >= 0` (cmp 㯠-1, 0, 1 ãè¿ã䏿¹æ¯è¼é¢æ°ã¨ãã)
ã§ãããã¨ãä¿è¨¼ããã¾ãã
```C++
#include
#include
int main()
{
std::cout << std::lerp(0.0, 10.0, 0.0) << '\n'; // 0
std::cout << std::lerp(0.0, 10.0, 0.3) << '\n'; // 3
std::cout << std::lerp(0.0, 10.0, 1.0) << '\n'; // 10
std::cout << std::lerp(0.0, 10.0, 1.2) << '\n'; // 12
}
```
### å®è£
åºæã®æ
å ±ãã¾ã¨ãã `` ãããã追å [(P0754R2)](https://wg21.link/P0754R2)
`__cpp_lib_byte`, `__cpp_lib_void_t` ã®ãããªæ¨æºã©ã¤ãã©ãªã®æ©è½ãã¹ããã¯ãããã®ä»ã©ã¤ãã©ãªã®ãã¼ã¸ã§ã³ãå®è£
åºæã®æ
å ±ãã¾ã¨ããç®çã® `` ãããã追å ããã¾ããã
ä¾ãã° C++20 以åã® MSVC ã®æ¨æºã©ã¤ãã©ãªã§ã¯ã`` ã¨ããç¬èªãããã«æ¨æºã©ã¤ãã©ãªã®æ©è½ãã¹ããã¯ããã¾ã¨ãããã¦ãã¾ããããC++20 以éã§ã¯ããããå®è£
ã«ããã¦ã`` ããããè¦ããã¨ã§ãããããå®è£
åºæã®æ
å ±ã«ã¢ã¯ã»ã¹ã§ããããå©ä¾¿æ§ãé«ã¾ãã¾ãã
### ä¾å¤ãæããªãæé»ã®å¤æãå¯è½ã調ã¹ã `is_nothrow_convertible` [(P0758R1)](https://wg21.link/P0758R1)
å `From` ããå `To` ã¸ã®æé»ã®å¤æãå¯è½ã§ãããã調ã¹ãåç¹æ§ã¯ã©ã¹ `std::is_convertible` ã C++11 ããå°å
¥ããã¾ãããããã®å¤æã `noexcept` ã§ããããã調ã¹ããããã¼ã¸ã§ã³ã¯å®è£
ããã¦ãã¾ããã§ããã
ãã®ãã¨ãåå ã§ã`std::decay_copy` ã®ææ¡ ([N3255](http://wg21.link/n3255)) ã«ããã¦ãé©å㪠`noexcept` ä¾å¤ä»æ§ãç§»æ¤æ§ã®ããæ¹æ³ã§å®ç¾©ã§ããªãåé¡ ([LWG 2040](http://wg21.link/lwg2040)) ãææããã¦ãã¾ããã
```C++
template
typename decay::type decay_copy(T&& v) noexcept(??? /* is_nothrow_convertible::value */);
```
C++20 ããã¯ã`noexcept` ãªæé»ã®å¤æãå¯è½ã§ãããã¨ã調ã¹ãæ°ããåç¹æ§ã¯ã©ã¹ `std::is_nothrow_convertible` ãå®è£
ããããã¨ã§åé¡ãè§£æ¶ã§ãã¾ãã
æ¢åã®æ¨æºã©ã¤ãã©ãªé¢æ°ã«ããã¦ãã`std::basic_string` ã®ã¡ã³ã颿°ãã³ãã¬ã¼ãã«ãããé©å㪠`noexcept` ä¾å¤ä»æ§ãå®ç¾©ããããã«æ´»ç¨ããã¾ãã
```C++
template
size_type find(const T& t, size_type pos = 0) const noexcept(is_nothrow_convertible_v>);
```
### ãã¤ã³ã¿ã©ã¤ã¯ãªãªãã¸ã§ã¯ãããã¢ãã¬ã¹ãåå¾ãã `std::to_address()` 颿° [(P0653R2)](https://wg21.link/P0653R2)
ãã¤ã³ã¿ã©ã¤ã¯ãªãªãã¸ã§ã¯ãã弿°ã«ã¨ããããã表ãã®ã¨åãã¢ãã¬ã¹ãçãã¤ã³ã¿ã§è¿ã颿° `std::to_address(p)` ã追å ããã¾ãããªãã¸ã§ã¯ãããã¤ã³ã¿åã®å ´åã¯ãã®å¤ãè¿ãããã以å¤ã®å ´åã`std::pointer_traits::to_address(p)` ã®ç¹æ®åãå®ç¾©ããã¦ãã¦ä½¿ããã°ãã®æ»ãå¤ããããã§ãªãå ´å㯠`std::to_address(p.operator->())` ã®æ»ãå¤ãè¿ãã¾ãã
### `` ãããã®é¢æ°ã® `constexpr` 対å¿ãå¼·å [(P0415R1)](https://wg21.link/P0415R1)
`` ããããæä¾ãã颿°ã®ãã¡ãè¤ç´ æ°ã®ååæ¼ç®ããã«ã ã®åå¾ãå
±å½¹è¤ç´ æ°ã®åå¾ãªã©ã`constexpr` é対å¿ã®æ°å¦é¢æ° (sqrt ãªã©) ã使ããã«å®è£
ã§ãããã®ã `constexpr` åããã¾ãã
### ã³ã³ãã¤ã«æè©ä¾¡ã®æèãå®è¡æè©ä¾¡ã®æèããå¤å¥ã§ãã `std::is_constant_evaluated()` 颿° [(P0595R2)](https://wg21.link/P0595)
C++17 ã¾ã§ã¯ãå®è¡ããã³ã¼ãããã³ã³ãã¤ã«æè©ä¾¡ãå®è¡æè©ä¾¡ãã«å¿ãã¦ä½¿ãåããæ¹æ³ã¯ããã¾ããã§ãããC++20 ã§ã¯ãã³ã³ãã¤ã«æè©ä¾¡ããã¦ããæèã§ã¯ `true` ãããã以å¤ã®å ´åã§ã¯ `false` ãè¿ã `std::is_constant_evaluated()` 颿°ã `` ãããã«è¿½å ããã¾ããä¾ãã°æ¨æºã©ã¤ãã©ãªã§ `constexpr` 対å¿ãã¦ããªããããªæ°å¦é¢æ°ãæä¾ããéãã³ã³ãã¤ã«æè©ä¾¡ã§ã¯ `constexpr` çã®å®è£
ããå®è¡æã«ã¯é `constexpr` ã®æ¨æºã©ã¤ãã©ãªã®å®è£
ãæä¾ãããã鏿ããããã¨ãã§ãã¾ãããªãã`std::is_constant_evaluated()` ã `if constexpr` ã® `( )` å
ã `static_assert` å
ã§ä½¿ãã¨å¸¸ã« `true` ã«è©ä¾¡ããã¦ãã¾ãã®ã§æ³¨æãå¿
è¦ã§ããåºæ¬çã«ã¯ `if (std::is_constant_evaluated())` ã¨æ¸ãã¾ãã
```cpp
#include
#include
#include
#include
constexpr float Sin_impl(float x2, int i, int k, float xn, long long nf)
{
return (i > 10) ? 0.0f : (k * xn / nf + Sin_impl(x2, i + 2, -k, xn * x2, nf * (i + 1) * (i + 2)));
}
constexpr float Sin(float x)
{
if (std::is_constant_evaluated())
{
return Sin_impl(x * x, 1, 1, x, 1);
}
else
{
return std::sin(x);
}
}
int main()
{
constexpr float Pi = 3.14159265f;
constexpr float theta = Pi / 4.0;
constexpr float x1 = Sin(theta); // ã³ã³ãã¤ã«æè¨ç®
float x2 = Sin(theta); // å®è¡æè¨ç®
std::cout << std::setprecision(16);
std::cout << x1 << '\n';
std::cout << x2 << '\n';
}
```
```
0.7071068286895752
0.7071067690849304
```
### æµ®åå°æ°ç¹æ°åã®ã¢ãããã¯æä½ãæ¡å¼µ [(P0020R6)](https://wg21.link/P0020R6)
`std::atomic` ã® `float`, `double`, `long double` åã®ç¹æ®åã«ãã¡ã³ã颿° `fetch_add()`, `fetch_sub()`, `operator+=()`, `operator-=()` ã追å ããã¾ãã
### `std::memory_order` ã `enum class` ã«å¤æ´ [(P0439R0)](https://wg21.link/P0439R0)
C++17 ã¾ã§ `enum` ã§å®ç¾©ããã¦ãã `std::memory_order` ããã¢ãã³ãª C++ ææ³ã¨åå®å
¨ã®ããã«ã`enum class` ã§å®ç¾©ãã仿§ã«å¤æ´ããã¾ããããã¾ã§ã®è¡¨è¨ã¯å®æ°ã§æä¾ãããããã«ãªããããæ¢åã®ã½ã¼ã¹ã³ã¼ãã¯å½±é¿ãåãã¾ãããã¾ãããã¤ããªäºææ§ã®ããã«ã`enum class` ã®åºåºåã®é¸æã¯å®è£
ã«ä»»ãããã¦ãã¾ãã
=== "C++17"
```C++
namespace std
{
typedef enum memory_order
{
memory_order_relaxed,
memory_order_consume,
memory_order_acquire,
memory_order_release,
memory_order_acq_rel,
memory_order_seq_cst
} memory_order;
}
```
=== "C++20"
```C++
namespace std
{
enum class memory_order /* : unspecified */
{
relaxed,
consume,
acquire,
release,
acq_rel,
seq_cst
};
inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
inline constexpr memory_order memory_order_consume = memory_order::consume;
inline constexpr memory_order memory_order_acquire = memory_order::acquire;
inline constexpr memory_order memory_order_release = memory_order::release;
inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
}
```
### `Hash` ãåä¸ã®æåãããªãéé åºé£æ³ã³ã³ããã©ããã®æ¯è¼ãå¯è½ã« [(P0809R0)](https://wg21.link/P0809R0)
C++17 ã¾ã§ã¯ãéé åºé£æ³ã³ã³ããã® `operator==`, `operator!=` ã«ã¤ãã¦ãã両è
ã® `Hash` 㨠`Pred` ãããããåä¸ã®æåãããªãå ´åã¯æªå®ç¾©åä½ãã¨è¦æ ¼ã«è¨ããã¦ãã¾ãããããããã©ã³ãã ãªã½ã«ãã使ãããã·ã¥é¢æ°ãæã¤ã³ã³ããåå£«ã®æ¯è¼ãã¦ã¼ã¹ã±ã¼ã¹ã¨ãã¦æ³å®ãããã¾ãã対å¿ããããã®å®è£
ãé£ãããªãã£ããã¨ãããC++20 ããã¯ãã®ãã¡ `Hash` ã«é¢ããè¨è¿°ãåé¤ããã¾ããã
```C++
#include
#include
#include
#include
template
struct RandomizedHash
{
size_t rnd;
RandomizedHash()
{
std::random_device rd;
rnd = std::uniform_int_distribution{}(rd);
}
size_t operator()(const Type& s) const
{
return (std::hash{}(s) ^ rnd);
}
};
int main()
{
std::unordered_map<:string int randomizedhash>> u1 =
{
{ "One", 1 }, { "Two", 2 }, { "Three", 3 },
};
std::unordered_map<:string int randomizedhash>> u2 =
{
{ "One", 1 }, { "Two", 2 }, { "Three", 3 },
};
// ããããç°ãªãããã·ã¥å¤ãè¿ã
const std::string s = "abcde";
std::cout << "u1: " << u1.hash_function()(s) << '\n';
std::cout << "u2: " << u2.hash_function()(s) << '\n';
std::cout << std::boolalpha;
// C++17 ã¾ã§ã¯æªå®ç¾©åä½ãC++20 ãã OK
std::cout << (u1 == u2) << '\n';
}
```
### å®è¡ç°å¢ã®ã¨ã³ãã£ã¢ã³ãå¤å¥ããããã®åæå®æ°ã追å [(P0463R1)](https://wg21.link/P0463R1)
ããã¾ã§ã® C++ ããã°ã©ã ã§ã¯ãã¿ã¼ã²ããã¢ã¼ããã¯ãã£ã®ãã¤ããªã¼ããå¤å¥ããéã«ããªããã¼ãªã³ã¼ããæ¸ãå¿
è¦ãããã¾ãããC++20 ããã¯ããªãã«ã¨ã³ãã£ã¢ã³ã表ã `endian::little`, ããã°ã¨ã³ãã£ã¢ã³ã表ã `endian::big`, å®è¡ç°å¢ã®ã¨ã³ãã£ã¢ã³ã表ã `endian::native` ã® 3 ã¤ã® `endian` åã®åæå®æ°ï¼å¤ã¯å®è£
ã«ä¾åï¼ã `` ã«å®ç¾©ããã`endian::native` ããã以å¤ã®å¤ã¨æ¯è¼ãããã¨ã§ãå®è¡ç°å¢ã®ãã¤ããªã¼ããå¤å¥ã§ããããã«ãªãã¾ããç¾å¨ã® C++ ã³ã³ãã¤ã©ã§ããªãã«ã¨ã³ãã£ã¢ã³ã§ãããã°ã¨ã³ãã£ã¢ã³ã§ããªãããã«ã¨ã³ãã£ã¢ã³ï¼PDP ã¨ã³ãã£ã¢ã³ãªã©ï¼ããµãã¼ããã¦ãããã®ã¯ããã¾ããããããã«ã¨ã³ãã£ã¢ã³ã®ç°å¢ã«ããã¦ã¯ã`endian::native` 㯠`endian::big` ã§ã `endian::little` ã§ããªãå¤ãæã¤ãã¨ã«ãªã£ã¦ãã¾ãã
```C++
#include
#include
int main()
{
if constexpr (std::endian::native == std::endian::little)
{
std::cout << "Little-endian\n";
}
else if constexpr (std::endian::native == std::endian::big)
{
std::cout << "Big-endian\n";
}
else
{
std::cout << "Middle-endian\n";
}
}
```
### åãã cv 修飾ã¨åç
§ãé¤å»ãã `std::remove_cvref` trait [(P0550R2)](https://wg21.link/P0550R2)
åãã `const` ã `volatile` ã®ä¿®é£¾ããã³åç
§ãé¤å»ãããã ãã§ãé
åãããã¤ã³ã¿ã颿°åãã颿°ãã¤ã³ã¿ã¸ã®å¤æã«ã¤ãã¦ã¯ä¸è¦ã§ãã£ã¦ããC++17 ã§ã¯ `std::remove_cv_t<:remove_reference_t>>` ã¨æ¸ãã¨é·ããªããã `std::decay` ã使ãã¨ããã±ã¼ã¹ãããããã¾ãããC++20 ãã㯠`std::remove_cv_t<:remove_reference_t>>` ã¨åã广ãæã¤ `std::remove_cvref` trait ã¨ããã®ãã«ãã¼å `std::remove_cvref_t` ã追å ãããçãæ¸ããããã«ãªãã¾ãã`std::remove_reference_t<:remove_cv_t>>` ã®ãããªé çªã®ééããé²ããã¨ã«ãã¤ãªããã¾ãã
### æ¨æºã©ã¤ãã©ãªã§ã®ä¸å¿
è¦ãª `std::decay` ã®ä½¿ç¨ãåé¿ [(P0777R1)](https://wg21.link/P0777R1)
C++17 ã®æ¨æºã©ã¤ãã©ãªã®è¦æ ¼ã§ã¯ `std::decay_t` ãããã 40 ç®æã§ä½¿ããã¦ãã¾ãããããã®ãã¡ cv 修飾ã®é¤å»ãåç
§ã®é¤å»ã ãã§ååãªç®æã«ã¤ãã¦ãå®è£
ã®æå³ãããæç¢ºã«ãããã `std::remove_reference_t` ããC++20 ããå°å
¥ããã `std::remove_cvref_t` ã«ç½®ãæãããã¾ããå
·ä½çã«ã¯ã`std::apply` ãã`std::optional`, `std::variant` ã®ä¸é¨ã®ã¡ã³ã颿°ãªã©ã§ç½®ãæããçºçãã¾ãã
### æ°å¦å®æ°ãæä¾ãã `` ããã [(P0631R8)](https://wg21.link/P0631R8)
ããã¾ã§ C++ ã®æ¨æºã©ã¤ãã©ãªã«ã¯æ°å¦å®æ°ãç¨æããã¦ãã¾ããã§ããï¼`M_PI` ãªã©ã¯æ¡å¼µï¼ãC++20 ããã¯æ°å¦å®æ°ãã¾ã¨ãã `` ãããã追å ããã13 種é¡ã®æ°å¦å®æ°ã®å¤æ°ãã³ãã¬ã¼ã宣è¨ã¨ããããã® `double` åã¸ã®ç¹æ®åã®å®ç¾©ãæä¾ããã¾ãã
夿°ãã³ãã¬ã¼ãã¯ãæ¨æºã©ã¤ãã©ãªã³ã³ã»ãã `floating_point` ã使ã£ã¦ã`std::numbers` åå空éã«æ¬¡ã®ããã«å®£è¨ããã¾ãã
```C++
template
inline constexpr T pi_v = 3.141592653589793238462643383279502884L;
```
åãã㦠`double` åã¸ã®ç¹æ®åã®å®ç¾©ã次ã®ãããªå®è£
ã§æä¾ããã¾ãã
```C++
inline constexpr double pi = pi_v;
```
C++20 ã§è¿½å ãããæ°å¦å®æ°ã®ä¸è¦§ã¯æ¬¡ã®ã¨ããã§ãã
| 宿°å | 説æ | binary128 ã«å
åãªç²¾åº¦ãæã¤å¤ |
|--------------|----------------|-----------------------------------------|
| e_v | e | 2.718281828459045235360287471352662498L |
| log2e_v | 2 ãåºã¨ãã e ã®å¯¾æ° | 1.442695040888963407359924681001892137L |
| log10e_v | 10 ãåºã¨ãã e ã®å¯¾æ° | 0.434294481903251827651128918916605082L |
| pi_v | åå¨ç (Ï) | 3.141592653589793238462643383279502884L |
| inv_pi_v | 1/Ï | 0.318309886183790671537767526745028724L |
| inv_sqrtpi_v | 1/âÏ | 0.564189583547756286948079451560772586L |
| ln2_v | 2 ã®èªç¶å¯¾æ° | 0.693147180559945309417232121458176568L |
| ln10_v | 10 ã®èªç¶å¯¾æ° | 2.302585092994045684017991454684364208L |
| sqrt2_v | â2 | 1.414213562373095048801688724209698078L |
| sqrt3_v | â3 | 1.732050807568877293527446341505872366L |
| inv_sqrt3_v | 1/â3 | 0.577350269189625764509148780501957456L |
| egamma_v | ãªã¤ã©ã¼ã®å®æ° | 0.577215664901532860606512090082402431L |
| phi_v | é»éæ° (Ï) | 1.618033988749894848204586834365638117L |
ã³ã¼ãã§ä½¿ç¨ããéã¯ã`using` 宣è¨ã«ãã£ã¦è¨è¿°ãçãã§ãã¾ãã
```C++
#include
#include
int main()
{
using std::numbers::pi;
using std::numbers::pi_v;
std::cout << 2.0 * pi << '\n';
std::cout << pi_v << '\n';
}
```
### `basic_string::reserve()` ã capacity ã縮å°ããªãããã« [(P0966R1)](https://wg21.link/P0966R1)
C++17 ã§ã¯ã`std::basic_string::reserve(size_type)` ã«ç¾å¨ã® `capacity()` ãããå°ããå¤ã渡ãããéãshrink-to-fit ãå®è¡ãããã¨ã許å¯ããã¦ãããããæ³¨ææ·±ã使ããªãã¨ã¡ã¢ãªã®åé
ç½®ãé »ç¹ã«å¼ãèµ·ãããå®è¡ææ§è½ãä½ä¸ããããã¨ãããã¾ãããã¾ããããã©ã«ã弿°ã¨ã㦠`0` ãå®ç¾©ããã¦ããã`s.reserve()` 㨠`s.shrink_to_fit()` ã§æ©è½ãéè¤ããã¨ããåé¡ããshrink-to-fit ãå®è¡ããããã©ã«ã弿°ãç¡ã `std::vector::reserve(size_type)` ã¨ã®ä¸è²«æ§ããªãã¨ããåé¡ãããã¾ãããC++20 ããã®æ°ãã仿§ã§ã¯ `std::vector` å´ã«åããã`std::basic_string::reserve(size_type)` ã«ç¾å¨ã® `capacity()` ãããå°ããå¤ã渡ãããéã«ã¯ä½ãããªããã¨ãä¿è¨¼ãããããã©ã«ã弿°ã廿¢ï¼äºææ§ã®ããã« deprecated æå®ã® `std::basic_string:reserve(void)` ãªã¼ãã¼ãã¼ãã追å ï¼ã¨ãªãããããã®åé¡ã解決ããã¾ãã
### 飿³ã³ã³ããã« `contains()` ã¡ã³ã颿°ã追å [(P0458R2)](https://wg21.link/P0458R2)
ããè¦ç´ ã飿³ã³ã³ããã«å«ã¾ãã¦ããã調ã¹ãããã® C++17 ã¾ã§ã®ã¤ãã£ãªã ã¯ãç´æçã§ãªãåå¿è
ã«ã¨ã£ã¦ãæå¿«ã§ã¯ããã¾ããã§ãããC++20 ããã¯ãè¦ç´ ã®åå¨ããã§ãã¯ãã `contains(key)` ã¡ã³ã颿°ã `std::map`, `std::multimap`, `std::set`, `std::multiset`, `std::unordered_map`, `std::unordered_multimap`, `std::unordered_set`, `std::unordered_multiset` ã«è¿½å ããã¾ãã
=== "C++17"
```C++
#include
#include
int main()
{
const std::unordered_map table =
{
{ 200, "OK" }, { 201, "Created" }, { 202, "Accepted" }
};
if (table.find(200) != table.end())
{
std::cout << "key exists\n";
}
}
```
=== "C++20"
```C++
#include
#include
int main()
{
const std::unordered_map table =
{
{ 200, "OK" }, { 201, "Created" }, { 202, "Accepted" }
};
if (table.contains(200))
{
std::cout << "key exists\n";
}
}
```
### ã³ã³ããããæå®ããè¦ç´ ãåé¤ããæä½ã«ä¸è²«ãã¦ä½¿ãã `std::erase()`, `std::erase_if()` 颿° [(P1209R0)](https://wg21.link/p1209r0)
ã³ã³ããããç¹å®ã®è¦ç´ ãåé¤ããã¨ããå¦çã¯ãã³ã³ããã®ç¨®é¡ã«ãã£ã¦æé©ãªæ¸ãæ¹ãç°ãªãã¾ãã`std::unordered_map` ã§ã¯ã¤ãã¬ã¼ã¿ã使ã£ã¦å
é ããè¦ç´ ãåé¤ãã¦ããã`std::list` ã§ã¯ã¡ã³ã颿°ã® `remove()` ã `remove_if()` ã使ãã`std::vector` ã§ã¯ `std::remove_if()` 㨠`erase()` ã¡ã³ã颿°ãçµã¿åããã¾ãããã®ããã«ã³ã³ããã®ç¹æ§ã«å¿ãã¦ã³ã¼ããæ¸ãåããã®ã¯å¤§å¤ã ã£ããããC++20 ã§ã¯ãã¹ã¦ã®ã³ã³ããåãã«é©åãªå®è£
ãæä¾ãããä¸è²«ãã¦ä½¿ããéã¡ã³ã颿° `std::erase()`, `std::erase_if()` ã追å ããã¾ãã
```C++
#include
#include
#include
#include
#include
int main()
{
std::vector v = { 3, 14, 1, 5, 92 };
std::list li = { 3, 14, 1, 5, 92 };
std::unordered_map<:string int> m = {
{ "aa", 3 }, { "bb", 14 }, { "cc", 1 }, { "dd", 5 }, { "ee", 92 } };
std::erase(v, 3);
std::erase(li, 3);
std::erase_if(m, [](const auto& p) { return p.second == 3; });
std::erase_if(v, [](auto n) { return n < 10; });
std::erase_if(li, [](auto n) { return n < 10; });
std::erase_if(m, [](const auto& p) { return p.second < 10; });
}
```
### ãã¤ãåã®åè§£éãã£ã¹ããè£å©ãã `std::bit_cast()` 颿° [(P0476R2)](https://wg21.link/P0476R2)
ããåã®ãªãã¸ã§ã¯ããæ ¼ç´ããã¦ãããã¤ãåã«å¯¾ãã¦ãå¥ã®åã®ãªãã¸ã§ã¯ãã¨è§£éãã¦ã¢ã¯ã»ã¹ããã㨠(type punning) 㯠C++ ã§ã¯ç¦æ¢ããã¦ãã¾ã (strict aliasing rule). `float` åã®å¤ã®ãã¤ãåã `std::uint32_t` åã¨ãã¦æ±ãã¨ãã®ééã£ãæ¹æ³ã¨ãã¦ã次ã®ãµã³ãã«ã®ããã« `reinterpret_cast` ã `union` ãç¨ããä¾ãããã¾ããããã¯ç´æçã«è¦ããå®éã»ã¨ãã©ã®ã³ã³ãã¤ã©ã§æå¾
éãåä½ãã¾ãããè¦æ ¼ä¸ã¯æªå®ç¾©åä½ã¨ãªã䏿£ãªã³ã¼ãã§ããæ£ãã㯠`std::memcpy()` ã使ãã¾ãã
```C++
#include
#include
#include
union FloatUint32
{
float f;
std::uint32_t u;
};
int main()
{
constexpr float f = 0.5f;
// æªå®ç¾©åä½
const std::uint32_t u1 = *reinterpret_cast(&f);
// æªå®ç¾©åä½
const std::uint32_t u2 = FloatUint32{ f }.u;
// OK
std::uint32_t u3;
std::memcpy(&u3, &f, sizeof(f));
std::cout << u1 << '\n';
std::cout << u2 << '\n';
std::cout << u3 << '\n';
}
```
ãããã`std::memcpy()` ã§ã¯å夿ã `constexpr` ã«ã§ãããã¾ããããã©ã«ãã³ã³ã¹ãã©ã¯ãå¯è½ã§ãªãåã«å¯¾å¿ããã«ã¯ `std::aligned_storage` ã¨çµã¿åãããå¿
è¦ããããªã©ãé©åãªå®è£
ã¯é¢åã§ãããC++20 ã§ã¯ããã®å®è£
ãã³ã³ãã¤ã©ãµãã¼ãã«ãã `constexpr` 対å¿ãå«ãã¦å®ç¾ãã `std::bit_cast()` 颿°ãæä¾ããã¾ãã
```C++
template
constexpr To bit_cast(const From& from) noexcept;
```
夿å
ã®å `To` ã¨å¤æå
ã®å `From` ã«ã¤ãã¦ã`sizeof(To) != sizeof(From)` ã®å ´åãã`std::is_trivially_copyable_v == false` ã¾ã㯠`std::is_trivially_copyable_v == false` ã®å ´åã«ã¯ã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªããããééããæ¸ãã广ãããã¾ãã
```C++
#include
#include
#include
int main()
{
constexpr float f = 0.5f;
constexpr std::uint32_t u = std::bit_cast<:uint32_t>(f);
std::cout << u << '\n';
}
```
### `` ã®é¢æ°ã®éå¹çãªå®è£
ãæ¹å [(P0616R0)](https://wg21.link/P0616R0)
C++17 ã§ã¯ã`std::accumulate()` 㯠`acc = binary_op(acc, *i)` ã¨ãã¦å®è£
ãããã¨è¦æ ¼ã«å®ãããã¦ããããããæ¬¡ã®ãããªã±ã¼ã¹ã§ `std::accumulate()` ã®æä¸ã« `std::string` ã®ã¢ãã±ã¼ã·ã§ã³ã大éã«çºçãã¦éå¹çã§ããã
```C++
#include
#include
#include
#include
int main()
{
std::vector<:string> words(100, "abc");
std::string s = "start";
std::string r = std::accumulate(words.begin(), words.end(), s);
std::cout << r << '\n';
}
```
C++17 ã® `std::accumulate()` ã®ä¸ã§è¡ããããã¨:
```C++
acc = acc + *i; // operator+(const std::string&, const std::string&)
++i;
... // ããè¿ã
```
C++20 ã§ã¯ã`std::move()` ã使ã `acc = binary_op(std::move(acc), *i)` ã¨ããå®è£
ã«å¤æ´ãããå³è¾ºå¤ã®æ¼ç®ã«å¯¾ããå¹ççãªå®è£
ãæä¾ããå (`std::string` ãªã©) ããæ©æµãåããããããã«ãªãã¾ãã
C++20 ã® `std::accumulate()` ã®ä¸ã§è¡ããããã¨:
```C++
acc = std::move(acc) + *i; // operator+(std::string&&, const std::string&)
++i;
...
```
`operator+(std::string&& lhs, const std::string& rhs)` ã¯åºæ¬çã« `lhs.append(rhs)` ã§ããæ¬¡ã®ããã«ãããããååãªãã£ãã·ãã£ã確ä¿ãããããã¡ã `std::accumulate()` å
ã§ä½¿ããããã«ããªãã¾ãã
```C++
#include
#include
#include
#include
int main()
{
std::vector<:string> words(100, "abc");
std::string s = "start";
s.reserve(s.size() + (word.size() * words.front().size())); // C++17 ã§ã¯ç¡æå³
std::string r = std::accumulate(words.begin(), words.end(), std::move(s));
std::cout << r << '\n';
}
```
`std::move()` ã使ããã®ä»æ§å¤æ´ã¯ãåã `` ãããã® `std::inner_product()` ã `std::partial_sum()`, `std::adjacent_difference()` ã«ãé©ç¨ããã¾ãã
### 2 ã®ç´¯ä¹æ°ã«é¢ããã¦ã¼ãã£ãªãã£é¢æ°ã追å [(P0556R3)](https://wg21.link/P0556R3), [(P1355R2)](https://wg21.link/P1355R2), [(P1956R1)](https://wg21.link/P1956R1)
ããæ´æ°ã 2 ã®ç´¯ä¹æ°ã§ãããã調ã¹ãããããæ´æ°ã«è¿ã 2 ã®ç´¯ä¹æ°ãæ¢ãããããå¦çã¯ãããã°ã©ãã³ã°ã§ããç»å ´ãã¾ãããC++17 ã®æ¨æºã©ã¤ãã©ãªã«ã¯å®è£
ããã¦ãã¾ããã§ãããC++20 ã§ã¯æ¬¡ã®ãããªé¢æ°ã追å ããã¾ãã
```C++
namespace std
{
template
constexpr bool has_single_bit(T x) noexcept;
template
constexpr T bit_ceil(T x);
template
constexpr T bit_floor(T x) noexcept;
template
constexpr T bit_width(T x) noexcept;
}
```
- 弿° `x` ã®ãããåã«å«ã¾ãã 1 ã 1 åã ãã§ããããå¤å®ãã `std::has_single_bit(x)`
- ã`x` ã 2 ã®ç´¯ä¹æ° (1, 2, 4, 8, ...) ã§ããããã¨åãæå³
- `x` 以ä¸ã§æå°ã® 2 ã®ç´¯ä¹æ°ãè¿ã `std::bit_ceil(x)`
- `x` 以ä¸ã§æå¤§ã® 2 ã®ç´¯ä¹æ° (ãã ã `x` ã 0 ã®å ´å㯠0) ãè¿ã `std::bit_floor(x)`
- `(1 + log2(x))` ã®æ´æ°é¨ (ãã ã `x` ã 0 ã®å ´å㯠0) ãè¿ã `std::bit_width(x)`
- ã`x` ã表ç¾ããããã«ä½ãããå¿
è¦ããã¨åãæå³
ãããã®é¢æ°ããå `T` ã符å·ãªãæ´æ°å (`unsigned char`, `unsigned short`, `unsigned int`, `unsigned long`, `unsigned long long`) ã®å ´åã®ã¿ãªã¼ãã¼ãã¼ã解決ã«åå ãã¾ãããªãã`std::bit_ceil(x)` ã«ã¤ãã¦ãçµæãå `T` ã§è¡¨ç¾ã§ããªãå ´åã®åä½ã¯æªå®ç¾©ã§ãã
```C++
#include
#include
int main()
{
for (unsigned i = 0; i <= 16; ++i)
{
std::cout << i << ": "
<< std::has_single_bit(i) << ' '
<< std::bit_ceil(i) << ' '
<< std::bit_floor(i) << ' '
<< std::bit_width(i) << '\n';
}
}
```
```
0: 0 1 0 0
1: 1 1 1 1
2: 1 2 2 2
3: 0 4 2 2
4: 1 4 4 3
5: 0 8 4 3
6: 0 8 4 3
7: 0 8 4 3
8: 1 8 8 4
9: 0 16 8 4
10: 0 16 8 4
11: 0 16 8 4
12: 0 16 8 4
13: 0 16 8 4
14: 0 16 8 4
15: 0 16 8 4
16: 1 16 16 5
```
### `std::list` 㨠`std::forward_list` ã®è¦ç´ åé¤ã¡ã³ã颿°ããåé¤ããè¦ç´ æ°ãè¿ãããã« [(P0646R1)](https://wg21.link/P0646R1)
`std::list` ã®ã¡ã³ã颿° `remove()` ã§è¦ç´ ãåé¤ããéãå®éã«åé¤ãããè¦ç´ æ°ãç¥ãã«ã¯ãåå¾ã§ `size()` ã®æ¯è¼ãè¡ããªããã°ãªãã¾ããã§ããããããã`std::forward_list` ã®å ´å㯠`size()` ã¡ã³ã颿°ãæããªããããO(n) ã®æä½ã§ãã `std::distance()` ã使ãå¿
è¦ãããã¾ãããC++20 ã§ã¯ã`std::list` ããã³ `std::forward_list` ã® `remove()`, `remove_if()`, `unique()` ã¡ã³ã颿°ããåé¤ãããè¦ç´ æ°ãæ»ãå¤ã¨ãã¦è¿ãããã«ãªãã¾ãããªããå¼ã³åºãå´ã§æ»ãå¤ã使ããªãå ´åã主è¦ã³ã³ãã¤ã©ã¯æé©åã§å¦çãçç¥ããããããã®ä»æ§å¤æ´ãå®è¡ææ§è½ã«ä¸ããå½±é¿ã¯ç¡ãã¨ããã¦ãã¾ãã
### è¦ç´ æ°ã決ã¾ã£ã¦ããé
ååãã©ããã調ã¹ãåç¹æ§ `std::is_bounded_array`, `std::is_unbounded_array` [(P1357R1)](https://wg21.link/P1357R1)
C++17 ã®æ¨æºã©ã¤ãã©ãªãæä¾ããåç¹æ§ã«ã¯ãé
åã®è¦ç´ æ°ã決ã¾ã£ã¦ãã (bounded) ãã©ãããå¤å®ãããã®ã¯ããã¾ããã§ãããC++20 ã§ã¯å©ä¾¿æ§ã®ããã«ãå `T` ãè¦ç´ æ°æ¢ç¥ã®é
ååã§ãããã調ã¹ãåç¹æ§ `std::is_bounded_array` ã¨ãå `T` ãè¦ç´ æ°æªç¥ã®é
ååã§ãããã調ã¹ãåç¹æ§ `std::is_unbounded_array` ã追å ããã¾ããã
```C++
#include
#include
int main()
{
std::cout << std::boolalpha;
std::cout << std::is_bounded_array_v << '\n'; // false
std::cout << std::is_bounded_array_v << '\n'; // false
std::cout << std::is_bounded_array_v << '\n'; // true
std::cout << std::is_unbounded_array_v << '\n'; // false
std::cout << std::is_unbounded_array_v << '\n'; // true
std::cout << std::is_unbounded_array_v << '\n'; // false
}
```
```
false
false
true
false
true
false
```
C++ æ¨æºã©ã¤ãã©ãªã®æ©è½ã§ã¯ãä¾ãã° `std::make_unique()` ãè¦ç´ æ°æ¢ç¥ã®é
ååãç¦æ¢ãã¦ãã¾ãããããããªã¼ãã¼ãã¼ããæ±ãã¨ãã«ããã®åç¹æ§ã便å©ã§ãã
```C++
#include
#include
int main()
{
auto p1 = std::make_unique(3);
auto p2 = std::make_unique(); // ã³ã³ãã¤ã«ã¨ã©ã¼
}
```
### `std::function` ã®ã ã¼ãã³ã³ã¹ãã©ã¯ã¿ã `noexcept` ã« [(P0771R1)](https://wg21.link/P0771R1)
å®è¡ææ§è½ãåä¸ããããããC++20 ã§ã¯ `std::function` ã®ã ã¼ãã³ã³ã¹ãã©ã¯ã¿ã `noexcept` ã«ãªãã¾ãããªããlibstdc++ 㨠libc++ ã§ã¯ææ¡æç¹ã§ãã§ã«å®è£
æ¸ã¿ã§ããã
### ``, `` ã®å¤ãã®é¢æ°ã `constexpr` ã« [(P0202R3)](https://wg21.link/P0202R3), [(P0879R0)](https://wg21.link/P0879R0)
C++20 ã§ã¯ `` ãããã® `std::swap()`, `std::exchange()` ããã³ã`` ãããã§æ¡ä»¶ãæºããå
¨é¢æ°ã `constexpr` ã«å¯¾å¿ãã¾ãã`std::all_of()` ã `std::sort()`, `std::reverse()` ãªã©ããã使ãããã¢ã«ã´ãªãºã 颿°ã `constexpr` ã«ãªãã¾ãã
`` ãããã§ `constexpr` ã«ãªããªãã®ã¯ä»¥ä¸ã®é¢æ°ã®ã¿ã§ãã
- `std::stable_partition()`, `std::inplace_merge()`, `std::stable_sort()`
- ã¡ã¢ãªã®ã¢ãã±ã¼ã·ã§ã³çãå¿
è¦ãªãã
- `std::shuffle()`, `std::sample()`
- `constexpr` 颿°ãæããªã `std::uniform_int_distribution` ã使ç¨ãããã
- `ExecutionPolicy` ã弿°ã«åã颿°
```C++
#include
#include
#include
constexpr int SumOfTop3(std::array a)
{
std::nth_element(a.begin(), a.begin() + 3, a.end()); // C++20 ã§ã¯ constexpr
return a[0] + a[1] + a[2];
}
int main()
{
constexpr int n = SumOfTop3({ 1, 8, 16, 4, 2 });
static_assert(n == 7);
std::cout << n << '\n'; // 7
}
```
```
7
```
### ãã¹ãã©ã¯ã¿ãèªåã§å¼ã°ãªã `delete` æ¼ç®åãªã¼ãã¼ãã¼ã [(P0722R3)](https://wg21.link/P0722R3)
C++17 ã§ã¯ãã¦ã¼ã¶å®ç¾©ã® `delete` ã®ä¸ã§ã¡ã³ã夿°ã«ã¢ã¯ã»ã¹ãããã¦ãããã§ã«ã¯ã©ã¹ã®ãã¹ãã©ã¯ã¿ãå¼ã°ãã¦ããããæªå®ç¾©ã®åä½ã«ãªãã¾ãã
```C++
#include
#include
struct Object
{
std::string m_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static void operator delete(void* p)
{
std::cout << "m_str: "
<< static_cast