C++20 でのビット操作

この投稿で、C++20 のライブラリ機能に関するプレゼンテーションを終了します。今日はクラス std::source_locationについて書きます およびビット操作用のいくつかの関数。

std::source_location

std::source_location ソースコードに関する情報を表します。この情報には、ファイル名、行番号、および関数名が含まれます。デバッグ、ログ記録、またはテスト目的など、呼び出しサイトに関する情報が必要な場合、この情報は貴重です。クラス std::source_location 定義済みの C++11 マクロ __FILE__ のより良い代替手段です そして __LINE__ したがって、使用する必要があります。

次の表は、std::source_location のインターフェースを示しています。 .

呼び出し std::source_location::current() 新しいソース ロケーション オブジェクトを作成します src. sr cは呼び出しサイトの情報を表します。現在、std::source_location をサポートする C++ コンパイラはありません .したがって、次のプログラム sourceLocation.cpp cppreference.com/source_location からです。

// sourceLocation.cpp
// from cppreference.com

#include <iostream>
#include <string_view>
#include <source_location>
 
void log(std::string_view message,
 const std::source_location& location = std::source_location::current())
{
 std::cout << "info:"
 << location.file_name() << ':'
 << location.line() << ' '
 << message << '\n';
}
 
int main()
{
 log("Hello world!"); // info:main.cpp:19 Hello world!
}

プログラムの出力は、そのソース コードの一部です。

C++20 では、ビットまたはビット シーケンスへのアクセスや操作が非常に快適になります。

ビット操作

新しい型 std::endian のおかげで、スカラー型のエンディアンを取得できます。

エンディアン

  • エンディアンは、ビッグ エンディアンまたはリトル エンディアンです。ビッグエンディアンとは、最上位バイトが最初に来ることを意味します。リトルエンディアンは、最下位バイトが最初に来ることを意味します。
  • スカラー型は、算術型、enum のいずれかです。 、ポインター、メンバー ポインター、または std::nullptr_t .

クラス endian すべてのスカラー型のエンディアンを提供します:

enum class endian
{
 little = /*implementation-defined*/,
 big = /*implementation-defined*/,
 native = /*implementation-defined*/
};

  • すべてのスカラー型がリトルエンディアンの場合、std::endian::native std::endian::little に等しい .
  • すべてのスカラー型がビッグエンディアンの場合、 std::endian::native 等しい to std::endian::big .

まれなケースもサポートされています:

  • すべてのスカラー型が sizeof の場合 1 したがって、エンディアンは重要ではありません。列挙子の値 std::endian::littlestd::endian::big 、および std::endian::native
  • プラットフォームが混合エンディアンを使用する場合、std::endian::native std::endian::big と等しくない std::endian::little でもありません .

次のプログラム getEndianness.cpp を実行すると x86 アーキテクチャでは、答えはリトルエンディアンです。

// getEndianness.cpp

#include <bit>
#include <iostream>

int main() {

 if constexpr (std::endian::native == std::endian::big) {
 std::cout << "big-endian" << '\n';
 }
 else if constexpr (std::endian::native == std::endian::little) {
 std::cout << "little-endian" << '\n'; // little-endian
 }

}
constexpr if ソース コードを条件付きでコンパイルできるようにします。これは、コンパイルがアーキテクチャのエンディアンに依存することを意味します。エンディアンについて詳しく知りたい場合は、同名のウィキペディアのページを読んでください。

ビットまたはビット シーケンスへのアクセスまたは操作

次の表は、すべての機能の最初の概要を示しています。

std::bit_cast 以外の関数 符号なし整数型 (unsigned char, unsigned short, unsigned int, unsigned long, または unsigned long long ).

プログラム bit.cpp 関数の使用法を示します。

// bit.cpp

#include <bit>
#include <bitset>
#include <iostream>
 
int main() {
 
 std::uint8_t num= 0b00110010;
 
 std::cout << std::boolalpha;
 
 std::cout << "std::has_single_bit(0b00110010): " << std::has_single_bit(num) 
 << '\n';
 
 std::cout << "std::bit_ceil(0b00110010): " << std::bitset<8>(std::bit_ceil(num)) 
 << '\n';
 std::cout << "std::bit_floor(0b00110010): " 
 << std::bitset<8>(std::bit_floor(num)) << '\n';
 
 std::cout << "std::bit_width(5u): " << std::bit_width(5u) << '\n';
 
 std::cout << "std::rotl(0b00110010, 2): " << std::bitset<8>(std::rotl(num, 2)) 
 << '\n';
 std::cout << "std::rotr(0b00110010, 2): " << std::bitset<8>(std::rotr(num, 2)) 
 << '\n';
 
 std::cout << "std::countl_zero(0b00110010): " << std::countl_zero(num) << '\n';
 std::cout << "std::countl_one(0b00110010): " << std::countl_one(num) << '\n';
 std::cout << "std::countr_zero(0b00110010): " << std::countr_zero(num) << '\n';
 std::cout << "std::countr_one(0b00110010): " << std::countr_one(num) << '\n';
 std::cout << "std::popcount(0b00110010): " << std::popcount(num) << '\n';
 
}

プログラムの出力は次のとおりです。

次のプログラムは、アプリケーションと関数 std::bit_floor の出力を示しています。 , std::bit_ceilstd::bit_width 、および std::bit_popcount 2 から 7 までの数字。

// bitFloorCeil.cpp

#include <bit>
#include <bitset>
#include <iostream>
 
int main() {

 std::cout << std::endl;
 
 std::cout << std::boolalpha;
 
 for (auto i = 2u; i < 8u; ++i) {
 std::cout << "bit_floor(" << std::bitset<8>(i) << ") = " 
 << std::bit_floor(i) << '\n';

 std::cout << "bit_ceil(" << std::bitset<8>(i) << ") = " 
 << std::bit_ceil(i) << '\n';

 std::cout << "bit_width(" << std::bitset<8>(i) << ") = " 
 << std::bit_width(i) << '\n';
 
 std::cout << "bit_popcount(" << std::bitset<8>(i) << ") = " 
 << std::popcount(i) << '\n'; 
 
 std::cout << std::endl;
 }
 
 std::cout << std::endl;
 
}

次は?

コルーチンに加えて、C++20 には並行性のために多くの機能があります。まず、C++20 には新しいアトミックがあります。浮動小数点値とスマート ポインター用の新しいアトミックが存在します。 C++20 では、アトミックの待機も有効になっています。スレッドを調整するために、セマフォ、ラッチ、およびバリアが機能します。また、std::thread std::jthread で改善されました . std::jthread の実行
は中断でき、そのデストラクタに自動的に参加します。