C++ テンプレート関数の呼び出し間違いをコンパイル時に検出する方法

C++

はじめに 今、次のようなテンプレート関数があるとしましょう このテンプレート関数には問題があります template<typename pointer_type_> inline void my_delete( pointer_type_& p ){ if( p ){ delete p; p = NULL; } } template<typename pointer_type_> inline void my_delete_array( pointer_type_& p ){</typename></typename>…

C++ NULLポインタ経由のメンバ関数呼び出し

C++

実際に試してみると死なない 実際に試したところでは特に死んだりはしないようです struct cfoo { void foo() const { printf( "foo\n" ); } }; static_cast<cfoo*>(0)->foo(); またこんな感じのも死なないようです struct cfoo { cfoo* find( const char* name ) c</cfoo*>…

C++ 配列の要素数を静的に取得する方法

C++

C では C では次のように実装します #define elementsof( a ) (sizeof((a))/sizeof((a)[0])) 通常はこれで構わないのですが、これだと間違ってポインタを渡してしまってもエラーになってくれたりはしません○できる int aaa[10]; int bbb[elementsof( aaa )];…

C++ イテレータ入門

C++

ここでは C++ の STL などで使われているイテレータというものについて簡単に説明します その前に 新人さんは仕事でのコードで独自のコンテナやイテレータを書いてはいけません それぞれのプロジェクトでは必ず使ってよいとされているコンテナなどは予め決ま…

C++ キャストの意味と危険性

C++

C++ の3つのキャストは Cスタイルのキャストの持つ3つの側面をそれぞれ独立させたものです static_cast static_cast はセマンティクスを維持したまま型を変えたいときに使います static_cast はビットパターンを変更する場合があります static_cast は変換…

C++ エイリアスと最適化の危険な関係

C++

エイリアス エイリアス(alias) とは別名という意味です 何の別名かというと lvalue の別名ということです他のオブジェクトのインスタンス(実体)を参照しているものがエイリアスです文法的にはポインタと参照がエイリアスです lvalue と rvalue エイリアス…

動的メモリ割り当て入門

ここでは malloc や new などの背後にある動的メモリ割り当ての仕組みについて説明しましょう はじめに この頃では初心者といえども STL のコンテナを使ったり new でオブジェクトを動的に確保するようなことはもう当たり前にやっていると思いますが、その仕…

買い占めなんてなかった

さて少し時間が余ったので、プログラミングの話からは外れますが、自分の頭で考えるということについて話してみましょうかいつも言っているようにプログラマの仕事というのはプログラムを書くことだけではありません プログラマは論理を扱う職業です プログ…

C++プログラマのためのアセンブラ入門(続き)

(一記事のサイズ制限を越えてしまうようなので分割。前回の続き)情報処理の試験で使う casl 2 と comet 2 を実装してみましょう 実装例 #if defined( _MSC_VER ) // C4351 : 新しい動作: 配列 '%1' の要素は既定で初期化されます // C4917 : 'identifier' …

C++プログラマのためのアセンブラ入門

はじめに 新人さんといわず中堅くらいになったプログラマでもアセンブラがわからないという人が最近は多いようです 「ポインタがわからない」「マルチスレッドがわからない」というようなことも結局はアセンブラを理解していないところが大きいように思いま…

カレンダー入門

はじめに 新人教育などでプログラムを書かせる場合、その人がイメージしやすい問題を与えるということが重要ですですから、まったくの初心者には「関数の仕様を渡して、その仕様通りの動作をする関数を書かせる」といった問題や「printf や malloc を書いて…

C++ コーディングの作法

ここではコーディング規約/コーディング標準(coding standards/coding guidelines/coding rules)の話をしましょう 既に明文化され公表されているコーディング規約は幾つもありますし、クライアントごとプロジェクトごとに従うべきコーディング規約というも…

お釣りの金種を最小にする支払い方

元の記事とは関係ないけどおまけ 金種 紙幣や硬貨の種類のことを金種といいます 金種計算 紙幣や硬貨の種類を考慮した金額の計算のことを金種計算と呼ぶようです 所持金と金額 物の値段はただの数値です 紙幣や硬貨の種類は関係ありません 100円のものを100…

stringprintf

C++

stringprintf ここでよく出てくる stringprintf というのは std::string用の sprintf ですデバッグ用です 例えば次のような使い方をしますが別にわざわざこんなものを用意しなくても printf で構いません OutputDebugString( tstringprintf( _T("%d\n"), n )…

C++ namespaceを使って既存のテンプレートをカスタマイズ

C++

namespace をうまく使うと既存のテンプレートをきれいにカスタマイズすることができます std::map と文字列の自然順比較 std::map のキーに std::string を使うとその要素はデフォルトでは辞書順に並びます これを自然順に並ぶようにするにはどうすればいい…

C++ テンプレート引数に応じた場合分け

C++

テンプレート内でのマルチバイト文字とワイド文字の扱いを例に、テンプレート引数に応じた場合分けを実現する方法について説明します テンプレート引数に応じて何か処理を分けたいというときには、その場合分けを別のテンプレートに追い出すことで実現できま…

数値Xを2,8,10,16進数で表示する

元の記事とは関係ないけどおまけ ループその1 それぞれの記数法で各桁を分解することができるでしょうか わからないときはまずは簡単なところからやりましょう 表示の前にまず桁数を数えるだけやってみましょう int log2_i( int n ){ int cdigits = 0; do{ …

数値Xの約数を数える

元の記事とは関係ないけどおまけ ループその1 何にもわからなかったら、まずは素朴に int divisors_count( int a ){ debug_printf( "{ " ); int result = 0; int n = 1; while( n <= a ){ if( !( a % n )){ if( n > 1 ){ debug_printf( ", " ); } debug_pri…

2つの数の最大公約数を求める

元の記事とは関係ないけどおまけ ループその1 何にもわからなかったら、まずは素朴に書いてみるといいでしょう int gcd( int a, int b ){ int result = 1; int halfof_min_ab = (( a < b ) ? a : b ) / 2; int m = 2; while( m <= halfof_min_ab ){ if( !( …

コマンドチェインの無効化に対応

例えば移動したディレクトリを記録しているときに、履歴に残っているディレクトリが途中で削除されてしまった場合には、そのディレクトリへ移動できないようにしたり、そのディレクトリを表す項目を淡色表示したい、というようなこともあるでしょう そこで、…

コマンドチェインに名前を付ける

Undo/Redoの履歴を表示したいときなどがあります このようなときコマンドのグループに名前が付いていると便利です コマンドチェインに名前を付けられるようにしてみましょう Undo コマンド管理クラスの実装 #define INVALID_COMMAND_ID (( uint32_t )-1) #de…

コマンドチェインの最初と最後を検知できるように

Undo/Redo の際、コマンドチェインの最初と最後のタイミングがわかると便利なときがあります コマンドチェインを実行するときに、最初と最後のタイミングも通知するようにしてみましょう Undo コマンドの基底クラスの実装 最初と最後のタイミングを通知する…

コマンドチェインの登録を途中で中止できるように

コマンドのグループ化に対応できるようになりましたが、途中でエラーが発生したときなどに、キャンセルするということができませんでした コマンドチェインを途中でキャンセルできるようにしてみましょう Undo コマンド管理クラスの実装 #define INVALID_COM…

コマンドチェインに対応

一度の操作で複数のコマンドを一括して Undo/Redo したいというときがありますが、前回のコードでは対応していませんでした コマンドのグループ化、コマンドチェインに対応しましょう Undo コマンド管理クラスの実装 #define INVALID_COMMAND_ID (( uint32_t…

初歩的な実装

Undo コマンド まずは Undo マネージャに登録するコマンドのインターフェイスを決めましょう Undo マネージャに登録するコマンドはつまり Undo 可能なコマンドということですが、この Undo 可能なコマンドはアプリケーション側が実装するものです そしてこの…

C++ Undo入門

はじめに どのようなアプリケーションでも Undo 機能はぜひとも欲しい機能の一つだと思いますが、残念ながら Undo を実現するための標準的なフレームワークというようなものは存在しません ですからアプリケーションに Undo の機能を追加しようとすれば一か…

エラーメッセージに行番号を加える

これまでのエラーメッセージでは起きたエラーが何かということは判りましたが、それがどこで起きたのかということは判りませんでした そこでエラーメッセージに行番号を加えてどこで発生したエラーなのかも判るようにしてみましょう 仕組み 解析器で改行を数…

解析器と構文木と評価器を分ける

前回 0 除算の実行時エラーの処理がノードのクラスにありました ノードのクラスなのに実行時のエラー処理まで持っているのは美しくないですね これはノードのクラスに評価器の機能まで持たせてしまっているのが原因でした 構文木と評価器とは分けてしまいま…

構文木を使う

ここまでは解析と評価を一度に行ってきましたが、普通は解析処理と評価/実行の処理を分けるようにします解析処理は入力文字列が文法に合っているかどうかをチェックしながら出現した演算子や数値などの文法要素を評価の順番に並べたリストを作ることを仕事…

コメントも書けるようにする

ここまでの入力文字列中に改行を使うことはできましたが、コメントを書くことはできませんでした そこで入力文字列中に C/C++ 風のコメントがあったときはその部分を無視することができるようにしてみましょう 仕組み コメントは式の評価には関係ないので構…