yossi-taharaのブックマーク (66)

  • 実践C++応用講座 第12回 ルールは単純だけど意外にややこしいメンバ・テンプレート | Theolizer®

    メンバ・テンプレートはにクラスやクラス・テンプレートの中で定義された「関数テンプレート」と「クラス・テンプレート」です。 クラス内で全て定義する場合は大差ありません。しかし、クラス外で定義する場合は、組み合わせがあっという間に増えるので、ややこしいです。 メンバ・テンプレートの中身をクラス外で定義する場合 一般のメンバ関数やクラス内定義クラスを外部で定義するのと同じですが、テンプレート・パラメータの分複雑です。 メンバ・テンプレートの明示的特殊化行う場合 こちらはクラス内ではできないと決められています。 クラス内のクラス・テンプレートの部分的特殊化行う場合 こちらはクラス内、クラス外の両方でできるようです。 2.クラス外定義その1 関数テンプレートやクラス・テンプレートの中身の定義をクラス外で行うケースです。 2-1.外側のクラスが通常クラスの場合 テンプレートでない普通のクラスの中でメン

    実践C++応用講座 第12回 ルールは単純だけど意外にややこしいメンバ・テンプレート | Theolizer®
  • 実践C++応用講座 第11回 decltypeとstd::declval | Theolizer®

    こんにちは。田原です。 今回は、ちょっと複雑なテンプレートを書く時に便利なdecltypeとstd::declvalです。decltypは既にちらほらつかってますが受け取った式の型を返します。declvalはその逆っぽい機能で受け取った型のインスタンスを返すふりをします。(実際には返さないです。何を言っているか判らないかも?) 1.decltype 1-1.ざっくりの意味 大雑把に説明するとdecltype(式)と書くと式の「型」を返します。 std::cout << TYPENAME(decltype(1+1)) << "\n"; // int しかし、例外があります。decltype(名前)と書いた場合は、その名前の型を返します。この「名前」は変数名や関数名、クラスのメンバ名です。関数名やメンバ関数名の時、その関数を名前だけで特定出来ない場合(オーバーロードされている時)はエラーになり

    実践C++応用講座 第11回 decltypeとstd::declval | Theolizer®
  • 実践C++応用講座 第9回 部分特殊化チックな関数テンプレートのオーバーロード | Theolizer®

    こんにちは。田原です。 前回はクラス・テンプレートの少し高度な部分特殊化の方法を解説しました。今回はこれの関数テンプレート版を解説します。とは言っても関数テンプレートには部分特殊化はありません。その代わりオーバーロードがあります。それを使ってプライマリー・テンプレートをオーバーロードする手法で部分特殊化的な機能を実現できます。その定型パターンを解説します。(実は私、定形パターンは使えますが自由自在にオーバーロードを使えるかというとちょっと無理かも。やはりテンプレートは難しいです。) 1.まずは考え方から クラス・テンプレートは専用で「部分特殊化」する構文が使えました。同じように関数テンプレートを部分特殊化しようとしてもエラーになります。 template<typename tType> void foo(tType) { } template<typename tType> void fo

    実践C++応用講座 第9回 部分特殊化チックな関数テンプレートのオーバーロード | Theolizer®
  • 実践C++応用講座 第7回 部分的特殊化で便利な標準ライブラリの仕組みとその使用例 | Theolizer®

    こんにちは、田原です。 前回は部分的特殊化する際によく使われる部品と、それらを使った部分特殊化の例を1つ上げました。そして、実はC++11以降、標準ライブラリ<type_traits>で非常に多数の便利な部品が提供されています。今回はその中からのほんの一部について仕組みと使い方を解説します。この辺りが分かれば、それ以外の比較的理解し易いものについてはリファレンスを見れば使えるようになると思います。 ところで、解説しないものの中には実は私もよく理解できていないものがあります。trivial(自明の)という概念をあまり理解できていません。定義を見ると超複雑なのです。memcpy()できるようなクラスのことをtrivially copyable classと呼ぶらしいです。 しかし、C++では結構普通に代入演算子が自動生成されますので、memcpyが必要になるケースは稀と思います。もし必要になっ

    実践C++応用講座 第7回 部分的特殊化で便利な標準ライブラリの仕組みとその使用例 | Theolizer®
    yossi-tahara
    yossi-tahara 2017/11/12
    第7回 部分的特殊化で便利な標準ライブラリの仕組みとその使用例 | Theolizer® https://theolizer.com/cpp-school2/cpp-school2-7/
  • 実践C++応用講座 第6回 部分的特殊化で良く使う部品とSFINAEの利用方法 | Theolizer®

    こんにちは。田原です。 クラス・テンプレートの部分特殊化や関数テンプレートのオーバーロードはある程度範囲の型に対してテンプレートを定義します。その「範囲」をかなり自由に指定することができます。今回はそれによく使われる幾つかの部品と、範囲指定するためにたいへん有用なSFINAEの利用方法について解説します。 1.constexprでコンパイル時定数を定義する C++11でconstexprキーワードが追加されました。これは部分特殊化やオーバーロードを積極的に使う場面でもよく使われます。他の使い方もありますが、今回は部分特殊化やオーバーロードで使われる比較的簡単な使い方について説明します。 まず、constexprは、「constant expression (定数式)」の略語だそうです。 そして、constexprは、グローバル変数、ローカル変数、staticメンバ変数の初期化付き宣言に指定

    実践C++応用講座 第6回 部分的特殊化で良く使う部品とSFINAEの利用方法 | Theolizer®
  • 実践C++応用講座 第5回 部分的特殊化とオーバーロード | Theolizer®

    こんにちは。田原です。 前回は明示的特殊化を解説しました。明示的特殊化(完全特殊化)は型を確定してプライマリー・テンプレートとは異なる振る舞いを定義する機能でした。部分的特殊化は対応する型を完全に決めるのではなく、ある程度の範囲の型に対してプライマリー・テンプレートとは異なる振る舞いを定義する機能です。関数テンプレートには部分的特殊化がありませんが、関数テンプレート自体を複数オーバーロード定義することで似たようなことができます。今回はこれらの基的な使い方を解説します。 1.クラス・テンプレートの部分的特殊化 冒頭に述べたように部分的特殊化は、型を完全に限定せずある程度の範囲に対してプライマリー・テンプレートとは異なるクラスを定義します。例えば次の例は「ポインタ型全て」について別途定義しています。 (typename.hは第2回で紹介した便利ツールです。) #include <iostre

    実践C++応用講座 第5回 部分的特殊化とオーバーロード | Theolizer®
  • 実践C++応用講座 第4回 明示的特殊化とテンプレート用語の解説 | Theolizer®

    こんにちは。田原です。 前回は明示的実体化について解説しました。今回は明示的特殊化について解説します。ちょっと似た用語ですので混乱しないようにして下さい。「実体化」と「特殊化」の違いです。またC++規格書は「特殊化」という用語をあまり直感的ではない使い方をしています。「明示的特殊化」があれば「暗黙的特殊化」もあると予想する人が多いと思いますがありません。他にも一般的な用法とは異なる使い方をされているため混乱しがちです。その辺りについても解説したいと思います。 1.明示的特殊化 明示的特殊化(Explicit specialization)は、最初に定義したテンプレート(プライマリ・テンプレートと呼びます)について、特定の型について異なる定義をできる仕組みです。 クラス・テンプレートと関数テンプレートのどちらとも、明示的特殊化をすることができます。 1-1.クラス・テンプレートの場合 まず簡

    実践C++応用講座 第4回 明示的特殊化とテンプレート用語の解説 | Theolizer®
  • 実践C++応用講座 第3回 分割コンパイルとテンプレートの「明示的」実体化 | Theolizer®

    class Foo { int mData; public: Foo(int iData); }; inline Foo::Foo(int iData) : mData(iData) { std::cout << "Foo::mData=" << mData << "\n"; } void Foo_test(); #include <iostream> #include "foo.h" void Foo_test() { Foo foo0(123); } #include <iostream> #include "foo.h" int main() { Foo_test(); Foo foo(10); } Wandboxで確認する。 foo.hの8行目にある”inline”を消してみて下さい。1-1.と同じくリンク時に多重定義(multiple definition)エラーになります。 と

    実践C++応用講座 第3回 分割コンパイルとテンプレートの「明示的」実体化 | Theolizer®
  • 実践C++応用講座 第2回目 関数テンプレートの基本 | Theolizer®

    1-1.まずはサンプルのマクロから 前回もマクロと比較しましたが、今回もマクロと比べてみます。 テンプレートの解説では、よくMAXマクロと比較して説明されることが多いですが、私もその例に倣います。 #include <iostream> #define MAX(a, b) (((a) >= (b))?(a):(b)) int main() { std::cout << MAX(11, 22) << "\n"; } MAX(a, b)マクロはパラメータaとbを比較して大きい方の値を返却します。 1-1-1.ちょっとうざいカッコ マクロの場合は特に カッコ()をしつこい位書いておくと安心です。 普通の関数のパラメータは関数に渡される時に計算されるため、パラメータは1つの変数として扱えるのに対し、マクロは文字列を展開しているだけなので、aに 1+1が渡されるとそれは2ではなく、1+1に展開される

    実践C++応用講座 第2回目 関数テンプレートの基本 | Theolizer®
    yossi-tahara
    yossi-tahara 2017/10/09
    テンプレートと領収書を例えてみました。
  • 実践C++応用講座 第1回目 クラス・テンプレート | Theolizer®

    さて、多くのテンプレート解説は関数テンプレートからの導入が多いです。しかし、関数テンプレートを使う時、多くは「型推論」と呼ばれる機能を一緒に使います。「型推論」は実はかなり高度な機能なのでイキナリ出てくると混乱しそうです。 そこで、今はまだ「型推論」が使えないクラス・テンプレートから解説し、その後で順次解説していきます。 2.テンプレートの重要な概念 テンプレートには様々な概念がありますが、中でも特に重要な概念をリストします。 更に上記を分類するための用語として「実体化」、「特殊化」があります。ただし、「部分的特殊化」は「特殊化」ではないなど、なかなか理解し辛いです。恐らくテンプレートの理解を阻む要因の1つになっていると思います。このややこし「特殊化」については後日解説したいと思います。 3.クラス・テンプレートの基 まずは、基的な機能から解説します。 3-1.サンプルの対象クラス サ

    実践C++応用講座 第1回目 クラス・テンプレート | Theolizer®
    yossi-tahara
    yossi-tahara 2017/10/01
    実践C++応用講座始めました。テンプレートを中心に解説していきます。よろしく。
  • 実践C++入門講座 第37回目 ムーブの使いどころ | Theolizer®

    こんにちは。田原です。 今回は、最後にムーブの使いどころについて解説します。ムーブはC++11前までは無かった機能ですので頻繁に使われるわけではありません。意外に使いどころが難しいです。しかし、実は標準ライブラリで有効に活用されている縁の下の力持ちです。その仕組を把握しておくとプログラミングの幅が広がります。 1.関数の戻り値の場合 前回、ちょっとだけ触れましたが、関数の戻り値にムーブを使うと性能が上がりそうに感じます。しかし、RVO(Return Value Optimization)やNRVO(Named Return Value Optimization)と呼ばれる最適化手法に任せた方がより性能が上がります。その見極めの話です。 1-1.ムーブといえどもメンバ変数はコピーする まず、ムーブは一切コピーせずに「移動」するものではありません。「移動」という言葉に反するように感じますが、そ

    実践C++入門講座 第37回目 ムーブの使いどころ | Theolizer®
    yossi-tahara
    yossi-tahara 2017/09/17
    入門講座最終回
  • 実践C++入門講座 第36回目 最後の特殊メンバ関数ムーブ・コンストラクタ | Theolizer®

    こんにちは。田原です。 今回は最後の特殊メンバ関数ムーブ・コンストラクタとその使い方について解説します。また、特殊メンバ関数は常に自動生成されるわけではありません。自動生成されないのはどんな時か、またその理由について説明します。 1.ムーブ・コンストラクタ 前回、前々回と特殊メンバ関数について解説してきましたが、その最後のものがムーブ・コンストラクタです。 まずは前回のサンプルにムーブ・コンストラクタを入れてみます。(解説の都合で少し内容を変えています。) ムーブ・コンストラクタの構文は自分と同じ型の右辺値参照を1つだけ受け取るコンストラクタです。 内容はムーブ・セマンティクスのお約束に従い「ムーブ」と言える処理にします。 下記の例では、管理しているmFooの所有権とポインタをムーブしています。 class Foo { int mData; public: Foo(int iData) :

    実践C++入門講座 第36回目 最後の特殊メンバ関数ムーブ・コンストラクタ | Theolizer®
  • 実践C++入門講座 第35回目 ムーブと右辺値参照と特殊メンバ関数と | Theolizer®

    こんにちは。田原です。 前回、6つの特殊メンバ関数の内の4つを解説しました。今回は残りの2つのうちの一つムーブ代入演算子とそれにまつわるムーブ・セマンティクス、そして、C/C++歴史上4番目のポインタ(的なもの)「右辺値参照」について解説します。ちなみに、1つ目はポインタ、2つ目は参照、3つ目はconst参照、そして4つ目が右辺値参照です。 1.ムーブ代入演算子 5つ目の特殊メンバ関数です。多くの場合、コンパイラが自動的に生成します。 前回の解説で使ったRAIIパターン・クラスであるBarの場合、次の29-33行目に書いたようなムーブ代入演算子が自動的に生成されます。 class Foo { int mData; public: Foo(int iData) : mData(iData) { std::cout << "Foo::Foo() : mData=" << mData << "\

    実践C++入門講座 第35回目 ムーブと右辺値参照と特殊メンバ関数と | Theolizer®
    yossi-tahara
    yossi-tahara 2017/09/04
    右辺値参照について少し珍しい視点から解説してみました。(間違いがなければよいのですが、少し心配;;)
  • 実践C++入門講座 第34回目 6個のスペシャルなメンバ関数 | Theolizer®

    こんにちは。暑い日が続いてます。ちょっと夏バテ気味の田原です。 さて、C++のクラスにはスペシャルなメンバ関数が6個あります。このように書くとなんだか特別でC++らしく非常に難しいメンバ関数がありそうですが、実は全くそんなことないです。日常的にありふれています。あなたが書いた「普通」のclassにもきっとはいってます。今回は、そんなメンバ関数について解説します。 1.特殊メンバ関数 規格書では “Special member functions”とかかれています。日語では「特殊メンバ関数」や「特別メンバ関数」と呼ぶ人が多いようです。 何が特別かと言いますと、コンパイラが自動的に定義することが有る点です。あなたがコードを書かなくても自動的にコンパイラがコードを用意してくれる便利なものです。 次の6個あります。 デフォルト・コンストラクタ デストラクタ コピー・コンストラクタ コピー代入演算

    実践C++入門講座 第34回目 6個のスペシャルなメンバ関数 | Theolizer®
  • 実線C++入門講座 第33回目 C++の型変換でバグを未然に防ごう | Theolizer®

    こんにちは。田原です。 C言語の明示的な型変換は1つしかありません。問答無用に変換するので使い方を誤りやすくバグの元になり勝ちです。それに比べC++の明示的な型変換は危険なものが別れているためそれを使わないよう避けておけば比較的安全です。 また、その一つのdynamic_castは遅いと聞くので測ってみたところ、面白い結果が出ましたので報告します。 1.まずは暗黙の型変換 C++は明示的に型を指定して変数や定数の型を変換する場合と、暗黙的(自動的)に変換される場合の2つがあります。まずは暗黙的な変換について簡単に説明します。(詳しい説明は複雑ですので、入門講座では扱いません。) 1-1. いつ暗黙の型変換が発生するのか? 関数に渡される時と演算される時に暗黙の型変換(自動変換)が発生します。 例えば、short x=10; foo(x);のように関数fooへshort型変数xが渡される時や

    実線C++入門講座 第33回目 C++の型変換でバグを未然に防ごう | Theolizer®
    yossi-tahara
    yossi-tahara 2017/08/20
    dynamic_castの速度測ってみました。遅いぞmsvc!!
  • 実践C++入門講座 第32回目 ちょっとイライラするconst。でも、実は頼もしい奴です。 | Theolizer®

    こんにちは。田原です。 書き換えてはいけない変数を間違って書き換えるバグのデバッグはたいへんです。問題発生時のログを精査するなどいつも苦労します。しかし、そんなこともあろうかとC++にはconstと言う概念が用意されています。constを付けた変数を書き換えようとするとコンパイル・エラーにすることでバグを事前に叩き潰すという仕組みです。constに一手間かけることで苦労を大きく削減する頼もしい仕組みなのです。 1.constの考え方 考え方は冒頭にも書いたように単純です。 「この変数は書き換えないよ。もし、書き換えていたら教えてね。」とコンパイラにお願いしているのです。そして、コンパイラは書き換えない筈の変数を書き換えるかもしれないコードを検出したらコンパイル・エラーにします。 実は、書き換えた時だけエラーにしてくれると「神」なのですが「書き換える可能性のあるコード」をエラーにします。その

    実践C++入門講座 第32回目 ちょっとイライラするconst。でも、実は頼もしい奴です。 | Theolizer®
  • 実践C++入門講座 第31回目 イテレータの仕組みと範囲ベースforの仕組み | Theolizer®

    こんにちは。田原です。 難しい話が続いたので、ちょっと気楽にfor文について解説します。C++ではC言語にはなかった「イテレータ」が追加されました。そして、C++11ではコードがスッキリして可読性が上がる範囲ベースforを使えるようになりました。今回はこれらの使い方だけでなく仕組みについても解説します。 1.イテレータの使い方 各種のコンテナに保存されている要素を枚挙するために設計されたクラスがイテレータです。使い方はポインタによく似せられていますが、実体はクラスです。(各コンテナの内部で定義されています。) 1-1.ポインタによる記述 例えば、std::vectorの内容をポインタで枚挙する時は次のように書くことができます。(終了判定は違和感があるかも知れませんね。) #include <iostream> #include <vector> int main() { std::vect

    実践C++入門講座 第31回目 イテレータの仕組みと範囲ベースforの仕組み | Theolizer®
    yossi-tahara
    yossi-tahara 2017/07/30
    コンテナとイテレータの簡易コードを使って仕組みを解説してます。
  • 実践C++入門講座 第30回目 「例外」の要注意事項 | Theolizer®

    こんにちは。田原です。 前回、例外の使い方とその便利良さを解説しました。 いつも退屈で憂なエラー処理の記述とテストをかなり削減できる当にありがたい機構なのですが、使い方が難しいです。その難しい部分(特に避けて通った方が良い部分)や各種の使用上のノウハウを解説します。 1.なるべくcatch(…)で例外を握りつぶさない 前回、catch(…)を最後に書くと、それまでのcatch()で捕まえることができなかった例外を捉えることができるけど、どんな例外かわからない旨、説明しました。 さて、例外はエラー処理の記述とテストを容易にするための仕組みです。 エラーの内容を把握し、自動リカバリを可能とする 例えば、ユーザにファイル名が不適切であることをメッセージ表示し、適切なファイル名を入力して貰うなどが考えられます。ヒューマンエラーが頻発しないことは期待できますし、ヒューマンエラーが発生した時、処理

    実践C++入門講座 第30回目 「例外」の要注意事項 | Theolizer®
  • 実践C++入門講座 第29回目 異常系プログラミングを簡単化する「例外」 | Theolizer®

    こんにちは。田原です。 今回から2~3回に分けて例外について解説します。C言語時代、例外がなかった頃のエラー処理はたいへんでした。一々関数の戻り値をチェックしてエラー処理を書く必要があったからです。それはもう退屈でテストは苦行でした。例外はそれらを大幅に楽にする優れた仕組みです。今回はまず例外の基的な使い方とメリットについて解説します。 1.基的な考え方 例外は2つの機能を持ちます。 エラーが発生したことを通知する。 エラーが発生した以降の処理を指定場所までスキップする。 1-1.古くからあるエラー処理方法 C言語時代は、関数の戻り値でエラーが発生したかどうかを返却し、呼び出し側で戻り値をチェックしてエラーが発生した時の処理を行っていました。 この方法はなかなか手間がかかります。まず、エラーが発生する関数を呼び出すたびにエラーチェックと、必要ならエラー処理を記述することになります。例え

    実践C++入門講座 第29回目 異常系プログラミングを簡単化する「例外」 | Theolizer®
  • 実践C++入門講座 第28回目 staticメンバ、および、クラス外でメンバを定義する | Theolizer®

    こんにちは。田原です。 前回まででクラスの基の重要部分の解説が終わりましたが、あともう少し説明しておくべきことが残ってます。今回はその残りのstaticメンバとクラス宣言の外でメンバを定義する方法などについて解説します。 1.クラスとオブジェクトとインスタンス 今まで、クラス型の変数などと呼んでましたが、クラス型の変数やnewで獲得したクラス実体のことを、インスタンスやオブジェクトと呼ぶことが多いようです。 クラスも含めてオブジェクトと呼ばれることもあります。例えば「オブジェクト指向プログラミング」ですね。 class Foo { int mData; public: Foo() : mData(123) { } }; int main() { Foo mFoo; Foo* pFoo=new Foo(); delete pFoo; } というプログラムがあるとき、mFooはFooクラスの

    実践C++入門講座 第28回目 staticメンバ、および、クラス外でメンバを定義する | Theolizer®