C++1z なんでも代入できるanyクラス
C++1zでは、コピー可能かムーブ可能であればどんな型でも代入できるany
クラスが入ります。C++には全ての型の継承元のobject
クラスというものはないので、その代わりにこのクラスを使えます。
このクラスのために、<any>
ヘッダが新規追加されます。
#include <iostream> #include <any> #include <string> int main() { std::any a = 3; // int値を代入 a = std::string("hello"); // stringオブジェクトを代入 // 中身を取り出す // 取り出せなかったらstd::bad_any_cast例外 try { std::string s = std::any_cast<std::string>(a); std::cout << s << std::endl; } catch (std::bad_any_cast& e) { std::cout << "bad_any_cast" << std::endl; } // 中身を取り出す // こちらは取り出せなかったらヌルポインタが返る if (std::string* s = std::any_cast<std::string>(&a)) { std::cout << *s << std::endl; } else { std::cout << "null" << std::endl; } }
出力:
hello hello
Boostと標準の差異
標準に採択されたany
は、Boostにあるany
とほぼ同じです。Boost 1.61.0時点のany
との差異は、constexpr
対応していることに加え、optional
とvariant
と共通の設計にするために、標準側に以下の機能があるくらいです:
この共通設計のために、Boostにある以下のメンバ関数はありません:
参照
- N1939 Any Library Proposal for TR2
- N3390 Any Library Proposal (Revision 1)
- N3508 Any Library Proposal (Revision 2)
- N3804 Any Library Proposal (Revision 3)
- N4529 Working Draft, C++ Extensions for Library Fundamentals, Version 2
- N4562 Working Draft, C++ Extensions for Library Fundamentals, Version 2
- P0220R0 Adopt Library Fundamentals TS for C++17
- P0220R1 Adopt Library Fundamentals V1 TS Components for C++17 (R1)
- P0032R0 Homogeneous interface for
variant
,any
andoptional
- P0032R1 Homogeneous interface for
variant
,any
andoptional
(Revision 1) - P0032R2 Homogeneous interface for
variant
,any
andoptional
(Revision 2) - P0032R3 Homogeneous interface for
variant
,any
andoptional
(Revision 3)
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。
C++1z shared_ptr::weak_type
C++1zから、shared_ptr
の入れ子型としてweak_type
が追加されます。
これは、shared_ptr<T>
に対するweak_ptr<T>
型の別名です。
shared_ptr
の要素型を取り出してweak_ptr
のテンプレート引数を埋めることが冗長なコードになっていたための対処です。
shared_ptr<T> sptr = …; // shared_ptrをweak_ptrに変換してラムダ式に渡す auto f = [wptr = typename decltype(sptr)::weak_type(sptr)] { // この関数が呼ばれたときには、wptrが指す先のオブジェクトが死んでいる可能性がある if (wptr.lock()) { … } }
参照
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。
次回のBoost.勉強会は札幌です
Boost.勉強会 #20 東京に参加された皆さま、おつかれさまでした。発表資料はboostjpの以下のページにまとめてあります。
次回のBoost.勉強会は、札幌で行います。主催は@ignis_fatuusさんです。
明日はBoost.勉強会 東京です
C++1z not_fn
これまで、述語(predicate)を反転させるためには、std::not1()
とstd::not2()
という関数がありました。
これらの関数はそれぞれ1引数の述語関数オブジェクト、2引数の述語関数オブジェクトを対象としますが、C++11で導入された可変引数テンプレートがあれば、任意の引数を受け取る述語を扱えます。そのため、新たにstd::not_fn()
という関数が定義されるようになります。
// <functional> namespace std { template <class F> unspecified not_fn(F&& f); }
この関数には、可変引数テンプレートの制限に引っかかることのない限り、任意の数の引数を受け取る述語関数オブジェクトを指定できます。
#include <cassert> #include <functional> int main() { assert(std::not_fn([] { return true; })() == false); assert(std::not_fn([](int) { return true; })(1) == false); assert(std::not_fn([](int, int) { return true; })(1, 2) == false); assert(std::not_fn([](int, int, int) { return true; })(1, 2, 3) == false); }
std::not()
という関数名にしないのは、not
が予約語だからです。
std::not_fn()
関数の追加にともない、以下の機能は非推奨となります:
std::not1()
std::not2()
std::unary_negate
std::binary_nagate
- 標準関数オブジェクトの
result_type
、argument_type
、first_argument_type
、second_argument_type
参照
- P0005R0 Adopt
not_fn
from Library Fundamentals 2 for C++17 - P0005R1 Adopt
not_fn
from Library Fundamentals 2 for C++17 - P0005R2 Adopt
not_fn
from Library Fundamentals 2 for C++17 - P0005R3 Adopt
not_fn
from Library Fundamentals 2 for C++17 - P0005R4 Adopt
not_fn
from Library Fundamentals 2 for C++17 - P0358R0 Fixes for
not_fn
- P0358R1 Fixes for
not_fn
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。
C++1z basic_string::data()メンバ関数の非const版
basic_string
クラスが保持している動的文字配列の生ポインタを取得するdata()
メンバ関数ですが、C++14まではconst
メンバ関数のみ用意されていました。
C++1zでは、非const
版のdata()
メンバ関数が追加されます。これにより、char*
を要求するインタフェースに対してstd::string
オブジェクトを使いやすくなります。
たとえば、なぜかchar*
を要求するWindowsのCreateProcess()
関数のコマンドライン引数には、
BOOL CreateProcess( LPCTSTR lpApplicationName, // 実行可能モジュールの名前 LPTSTR lpCommandLine, // コマンドラインの文字列 ←これ LPSECURITY_ATTRIBUTES lpProcessAttributes, // セキュリティ記述子 LPSECURITY_ATTRIBUTES lpThreadAttributes, // セキュリティ記述子 BOOL bInheritHandles, // ハンドルの継承オプション DWORD dwCreationFlags, // 作成のフラグ LPVOID lpEnvironment, // 新しい環境ブロック LPCTSTR lpCurrentDirectory, // カレントディレクトリの名前 LPSTARTUPINFO lpStartupInfo, // スタートアップ情報 LPPROCESS_INFORMATION lpProcessInformation // プロセス情報 );
C++1zでは以下のようにして引数を渡せます:
std::string applicationName; std::string commandLineArgs; // ... if (CreateProcess(applicationName.data(), commandLineArgs.data(), /* etc. */)) { // etc. } else { // handle error }
参照
- P0272R0 Give
std::string
a non-const.data()
member function - P0272R1 Give
std::string
a non-const.data()
member function. - 文字列取得バッファとしての
std::string
リターンズ - yohhoyの日記
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。
C++1z emplace_frontとemplace_backで追加された要素を返す
シーケンスコンテナのemplace_front()
メンバ関数とemplace_back()
メンバ関数は、C++14では戻り値型がvoid
でしたが、C++1zでは追加された要素への参照が返るようになります。
これは、追加した要素をすぐ使いたい場合に、以下のような冗長なコードになっていた問題への対処です:
// case 1 my_container.emplace_back(…); my_container.back().do_something(…); // case 2 my_container.emplace_back(…); do_something_else(my_container.back());
C++1zでは、このような状況で以下のように書けるようになります:
// case 1 my_container.emplace_back(…).do_something(…); // case 2 do_something_else(my_container.emplace_back(…));
戻り値の型の変更は、ABIを破壊せず、パフォーマンスにも影響はありません。
変更対象は、シーケンスコンテナのemplace_front()
とemplace_back()
、およびqueue
クラスとstack
クラスのemplace()
メンバ関数になります。
push_front()
とpush_back()
は変更なしで、戻り値の型はこれまで通りvoid
です。
参照
- P0084R0 Emplace Return Type
- P0084R1 Emplace Return Type (Revision 1)
- P0084R2 Emplace Return Type (Revision 2)
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。
C++1z owner_lessで任意の要素型を持つshared_ptr同士を比較できるようにする
所有権ベースの小なり比較を行うstd::owner_less
関数オブジェクトですが、そのクラステンプレートのパラメータによってスマートポインタの要素型を制約してしまうため、以下のような比較ができませんでした。
shared_ptr<int> sp1; shared_ptr<void> sp2; shared_ptr<long> sp3; weak_ptr<int> wp1; owner_less<shared_ptr<int>> cmp; cmp(sp1, sp2); // コンパイルエラー cmp(sp1, wp1); cmp(sp1, sp3); // コンパイルエラー cmp(wp1, sp1); cmp(wp1, wp1); // コンパイルエラー
C++1zでは、std::owner_less
クラステンプレートにvoid
の特殊化版が定義され、そのバージョンでは関数テンプレートの関数呼び出し演算子を持つようになります:
// デフォルトテンプレート引数がvoidになり、 template<class T = void> struct owner_less; // voidに対する特殊化が追加 template<> struct owner_less<void> { template<class T, class U> bool operator()(shared_ptr<T> const&, shared_ptr<U> const&) const; template<class T, class U> bool operator()(shared_ptr<T> const&, weak_ptr<U> const&) const; template<class T, class U> bool operator()(weak_ptr<T> const&, shared_ptr<U> const&) const; template<class T, class U> bool operator()(weak_ptr<T> const&, weak_ptr<U> const&) const; typedef unspecified is_transparent; };
これによって、異なる要素型を持つスマートポインタや、shared_ptr<void>
のような特殊な要素型を持つスマートポインタとの比較ができるようになります。
参照
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。
C++1z 時間の丸め演算
時間ユーティリティライブラリの<chrono>
には、精度が下がる単位変換をする場合に使用するduration_cast()
関数があります。
C++1zでは、このときの丸め演算をユーザーが選択するための機能が導入されます。
まず、整数を時間間隔の値型とするduration
のための、floor()
(切り下げ)、ceil()
(切り上げ)、round()
(最近接偶数への丸め)。それと符号あり整数の時間間隔を持つduration
のためのabs()
(絶対値)。
#include <iostream> #include <chrono> using namespace std::chrono; int main() { milliseconds ms(2500); seconds sec = round<seconds>(ms); // 500は精度落ちする std::cout << sec.count() << std::endl; // 2 }
それと、そのduration
を持つtime_point
のための、floor()
、ceil()
、round()
が入ります。
Boost 1.61.0時点のBoost.Chronoライブラリには、duration
に対するfloor()
、ceil()
、round()
があります。
参照
- Boost.Chrono
duration
の丸め演算 - Faith and Brave - C++で遊ぼう duration_cast
と浮動小数点数型 - Faith and Brave - C++で遊ぼう- 浮動小数点数の
duration
型 - Faith and Brave - C++で遊ぼう - P0092R0 Polishing
<chrono>
- P0092R1 Polishing
<chrono>
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。
C++1z hypot関数の3引数版
C++11で<cmath>
に追加されたhypot()
関数ですが、2引数(2次元)の演算のみが用意されていました。
C++1zでは、3引数版が追加されます。動機としては、科学計算や工学アプリケーションで3次元の演算をすることが多いためだそうです。
// <cmath> namespace std { double hypot(double x, double y, double z); float hypot(float x, float y, float z); long double hypot(long double x, long double y, long double z); }
この関数の効果:
参照
- P0030R0 Proposal to Introduce a 3-Argument Overload to
std::hypot
- P0030R1 Proposal to Introduce a 3-Argument Overload to
std::hypot
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。