C++ TIPS 2
をテンプレートにして作成
Check
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#include(C++TipsMenu,notitle)
* 定数の定義と静的構造体テーブルを同時に作るマクロ [#b36e...
定数の定義をソースコード上で行う場合、定数の定義と値の定...
通常はこのように書きます。
#sh(cpp){{
enum EnumHoge { hoge, fuga, piyo };
struct HogeHoge {
EnumHoge id;
float value;
const char* name;
} const table[] = {
{ hoge, 1.0f, "hoge" },
{ fuga, 2.0f, "fuga" },
{ piyo, 3.0f, "piyo" },
};
}}
enumの定義と構造体の定義が冗長で、名前の文字列の定義も冗...
しかし、魂を悪魔(#define)に売り渡せば、一発で記述できます。
#sh(c){{
// ここで定数を定義する(冗長でない単一の記載で済ませる)
#define LIST \
DEF(hoge, 1.0f), \
DEF(fuga, 2.0f), \
DEF(piyo, 3.0f)
// enumの生成
#undef DEF
#define DEF(a, b) a
enum EnumHoge { LIST };
// 構造体の生成
#undef DEF
#define DEF(a, b) {a, b, #a}
struct HogeHoge {
EnumHoge id;
float value;
const char* name;
} const table[] = { LIST };
}}
使用例
#sh(cpp){{
#include <stdio.h>
int main(int ac, char*av []) {
for (size_t n = 0; n < sizeof(table)/sizeof(HogeHoge);...
printf("table[%d] = id:%d value:%f name='%s'\n", n, ...
}
}
}}
結果
table[0] = id:0 value:1.000000 name='hoge'
table[1] = id:1 value:2.000000 name='gufa'
table[2] = id:2 value:3.000000 name='piyo'
ideone: http://ideone.com/HEIsAa#view_edit_box
* コンテナに対して、pushとpush_backを自動判別して追加する...
#sh(cpp){{
// decltypeを使ってコンテナに要素を追加する
// push_back()を持っている場合 ...
template <typename CT, typename VT>
inline auto push_to_container(CT& container, VT&& val, ...
{
return container.push_back(val);
}
// push()がある場合 ...
template <typename CT, typename VT>
inline auto push_to_container(CT& container, VT&& val) ...
{
return container.push(val);
}
}}
使用例
#sh(c){{
std::vector<int> hoge;
std::priority_queue<int> fuga;
...
push_to_container(hoge, 1); // hoge.push_back(1)が呼ばれる
push_to_container(fuga, 1); // fuga.push(1)が呼ばれる
}}
参考にしたページ
[[メンバー関数の存在を確かめる方法>http://codelogy.org/ar...
* VC++でイテレーターを高速化する [#xa008aee]
VC++では、イテレーターの範囲チェックが行われており、安全...
以下の定義を行うことで、範囲チェックを無効にできます。([[...
#define _SECURE_SCL 0
ちなみに、以下の設定で範囲チェックが有効になります。
#define _SECURE_SCL_1
#define _HAS_ITERATOR_DEBUGGING 1
* boost mpl map for_each覚え書き [#vd3ad1a2]
boost::mplのvectorやmapをfor_eachするサンプル。
mapのkeyだけ回すmap_keysのようなフィルタの例も作ってみま...
#sh(cpp){{
#include <iostream>
#include <vector>
#include <string>
#include <typeinfo>
#include <boost/mpl/list.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/key_type.hpp>
using namespace boost;
using namespace std;
struct Disp {
template <class Type>
void operator()(const Type&) const {
cout << typeid(Type).name() << endl;
}
template <typename K, typename V>
void operator()(const mpl::pair<K,V>&) const {
cout << typeid(K).name() << "," << typeid(V).nam...
}
} disp;
int main()
{
typedef mpl::list<int, std::string, char, std::vecto...
typedef mpl::map<mpl::pair<int,char>, mpl::pair<int,...
cout << "mpl list test" << endl;
mpl::for_each<tl>(disp);
cout << "mpl map test" << endl;
mpl::for_each<t2>(disp);
cout << "mpl map key_type test" << endl;
mpl::for_each<t2, mpl::lambda<mpl::key_type<t2, mpl:...
cout << "finish" << endl;
return 0;
}
}}
cpp_akiraさんのページにあったサンプルにmapを足してみまし...
http://ideone.com/rrk1ZY
* enumをコンテナのように扱う [#m6e894fd]
http://stackoverflow.com/questions/1390703/enumerate-over...
* http://ideone.com/J6ThVM [#h9126ac3]
* 普通の配列をboost:arrayに化けさせる [#wd8b9f45]
配列をboost::arrayやstd::vectorに置き換えてしまえばよいの...
既存の配列をboost::arrayに見せかけるツールを作りました。
template <typename T, size_t N>
inline boost::array<T,N>& to_array(T(&ar)[N]) {
return *reinterpret_cast<boost::array<T,N>*>(&ar...
}
template <typename T, size_t N>
inline const boost::array<T,N>& to_array(const T(&ar)[N]...
return *reinterpret_cast<const boost::array<T,N>...
}
to_array(<配列変数>); で、boost::array<型,サイズ> に変換...
これで、生の配列変数に対して、iteratorとか、size()とか、s...
ideone: http://ideone.com/oi43Mo
* 静的な文字列リテラルは、同名のものは同じアドレスを示す ...
プログラム中に"hoge"のように記載する文字列リテラルは、リ...
それを利用して、静的リテラルのアドレスをハッシュ値として...
#include <iostream>
const char* s1 = "hoge";
const char* s2 = "hoge";
int main(int ac, char*av[]) {
const char* s3 = "hoge";
std::cout << "s1 == s2 : " << (s1 == s2) << std::en...
std::cout << "s1 == s3 : " << (s1 == s3) << std::en...
std::cout << "s1 == 'hoge' : " << (s1 == "hoge") << std...
}
output
s1 == s2 : 1
s1 == s3 : 1
s1 == 'hoge' : 1
http://ideone.com/fJz5e
* 整数型配列の初期化 [#e87c5d4b]
クラスインスタンスの整数型配列をゼロで初期化するには、初...
before
class Hoge {
int a[10];
hoge() {
memset(&a[0], 0, sizeof(a));
}
}:
after
class Hoge {
int a[10];
hoge() : a() {
}
};
http://ideone.com/E3rEc
* 多重継承したクラスをnewの配置構文で確保したときの落とし...
多重継承したクラスのポインタは、親クラスのポインタにキャ...
class C : public A, public B {...}
C* c = new C;
assert((A*)c == (B*)c); // assertで停止
ポインタの値で比較するときは注意が必要。
同じ理由で、newの配置構文でクラスインスタンスを確保した場...
class C : public A, public B {...}
void* buffer = malloc(sizeof(C));
C* c = new(buffer) C;
B* b = c; // B*に代入
b->~B(); // ~B()がvirtualならば、デストラクタはA,Cとも...
free(b); // bの値はbufferと異なるので死にます
↓ ideone.comでのサンプル~
http://ideone.com/LdCNi
* == true で比較してはいけない理由 [#jcd6c4c2]
if文で値をbooleanとして比較するとき、trueと==で比較すると...
※ C++ では、intとbool値と比較しても、左辺値に対して暗黙の...
#include <stdio.h>
int main(int ac, char* av[]) {
int a = 2;
if (a) printf("a is true\n"); else printf("...
if (a == true) printf("a is true\n"); else printf("...
if (a != false) printf("a is true\n"); else printf("...
if (static_cast<bool>(a) == true)
printf("a is true\n"); else printf("...
return 0;
}
結果
a is true
a is false
a is true
a is true
"a == true" で比較したときだけ、結果が異なる。
http://ideone.com/UbvzC
* 仮想関数の部分オーバーライドについて [#wc903ad4]
class Base {
public:
virtual void hoge() = 0;
virtual void hoge(int a) { printf("a=%d\n", a); }
};
class Sub : public Base {
public:
virtual void hoge() { printf("hoge\n"); }
};
このように仮想関数を部分的にオーバーライドした場合、警告...
回避するには、 class Subに、"using Base::hoge; "を加える...
本来なら同名のオーバーライドを避けるべきである。
http://stackoverflow.com/questions/2057823/issues-with-pa...
* #defineマクロとの戦い [#n3d01c1c]
#define hoge(x) HOGE(x)
などで、別名を無理やり定義されてしまっているのをすり抜け...
- 方法1~
(ns::function) のようにnamespace付きで()で囲む~
例
(std::printf)("hoge") ; // printfが#defineされていてもオ...
- 方法2~
関数名と引数リストの間に空の#defineを挟む~
例
#define FOO
printf FOO("hoge"); // printfが#defineされていてもオリジ...
** コード例 (http://ideone.com/S44K6) [#gaad9cff]
#include <stdio.h>
namespace foo {
void hoge(const char* const msg) { printf("small hoge : ...
void HOGE(const char* const msg) { printf("LARGE HOGE : ...
}
#define hoge(msg) HOGE(msg)
#define FOO
int main(int ac, char* av[]) {
foo::hoge("ns::function");
(foo::hoge)("(ns::function)");
foo::hoge FOO("ns::function FOO");
};
output
LARGE HOGE : ns::function
small hoge : (ns::function)
small hoge : ns::function FOO
* boost pool [#s2f524fb]
- boost poolには、pool, object_pool, singleton_poolの3種...
- pool
-- malloc/freeを行う
-- コンストラクタでサイズを指定
-- コンストラクタで指定サイズのメモリをアロケート/フリー...
-- 指定サイズのN倍も可能 (ordered)
-- orderedと通常がある。
- object_pool
-- クラスのインスタンスを生成/破棄する
-- orderedのみ
- singleton_pool
--サイズ別にシングルトンとして動作する。
--シングルトンとして使える。
--vectorなどSTLのコンテナのアロケーターとして使える
--メモリの解放にはpurge_memoryしかない。(全放棄)
** orderedとは [#vc6ee3bd]
- 必ずメモリアドレスが順番になる(連続する)
- orederdだと、破棄したメモリブロックの再利用はされない
- 解放するには、release_memoryを呼ぶ(アロケートブロックが...
-非orderedが一つでも混在していると、release_memoryができ...
- おそい
**通常版(非orederd) [#ha2b1cac]
-破棄したメモリブロックが再利用される
-release_memoryはできない
-全部破棄のpurge_memoryは可
-連続したメモリブロックを確保できない
*** ordered、非orderedともに一長一短で使いにくい [#r8f6db...
* オーバーライドした関数の戻り値は、基本クラスの定義の戻...
#include <stdio.h>
struct Base {
virtual Base* create() = 0; // create new instance
virtual Base* clone() = 0; // create and copy i...
virtual void print() = 0;
};
struct Sub : Base {
Sub() {}
Sub(const Sub& sub) {} // copy constructor
Sub* create() { return new Sub(); }
Sub* clone() { return new Sub(*this); }
void print() { printf("I am Sub\n"); }
};
int main(int ac, char* av[]) {
Base* base1 = Sub().create();
Base* base2 = base1->clone();
base2->print();
return 0;
}
- 実行結果~
http://t.co/ASDjAEvI
* boost:multiindexは便利 [#md6c228e]
http://d.hatena.ne.jp/faith_and_brave/20091126/1259226643
* virtualやポインタを使わず、サブクラスの生オブジェクトを...
// BaseClassのサブクラスをコンテナにいれるためのクラス
// このクラスを使うことで、ポインタを使わず動的ポリモ...
template <typename BaseClass, size_t MaxSize>
struct DynamicPolymorphism : BaseClass {
uint8_t body[MaxSize - sizeof(BaseClass)];
DynamicPolymorphism() : BaseClass() {}
DynamicPolymorphism(const DynamicPolymorphism& m)...
memcpy(body, m.body, sizeof(body));
}
template <typename SubClass>
DynamicPolymorphism(const SubClass& m) : BaseClas...
SubClass& self = reinterpret_cast<SubClass&>(...
self = m;
}
template <typename SubClass>
void operator = (const SubClass& m) {
SubClass& self = reinterpret_cast<SubClass&>(...
self = m;
}
template <typename SubClass>
operator SubClass& () { return reinterpret_cast<S...
};
※これでunionから開放されます
比較的サイズが小さいクラスを実体のままコンテナに格納する...
例
class Car {
int cylinders; /* 気筒数*/
int displacement; /* 排気量 */
};
class Track : public Car { int payload = 1000; } // 最...
class Bus : public Car { int maxPeoples = 30; } // 乗...
vector<Car> carList;
carList.push_back(Truck()); // NG TruckがCarでスライ...
carList.push_back(Bus()); // NG BusがCarでスライシン...
vector<Car*> carList2;
carList2.push_back(new Truck()); // OK Truckの情報も...
carList2.push_back(new Bus()); // OK maxPeoplesの情報...
ポインタを使えば解決するけど、小さいオブジェクトを全部new...
unionを使った解決方法
class AllCar {
enum Type { Truck, Bus };
Type type;
int cylinders;
int displacement;
union {
int payload;
int maxPeoples;
};
};
vector<AllCar> allCarList;
AllCar truck;
truck.type = AllCar::truck;
allCarList.push_back(truck);
DynamicPolymorphismを使った例
class Car {
enum Type { Truck, Bus };
Type type;
int cylinders; /* 気筒数*/ int displacement; /* 排気...
};
class Track : public Car { int payload = 1000; } // 最...
class Bus : public Car { int maxPeoples = 30; } // 乗...
typedef DynamicPolymorphism<Car, max(sizeof(Truck), si...
vector<AllCars> allCars;
allCars.push_back(Truck()); // AllCarsは継承クラスの...
allCars.push_back(Bus());
Truck& t = allCars.front(); // DynamicPolymorphismのオ...
Bus& t = allCars[1];
* operator new の効力範囲 [#tdb48b30]
#include <stdio.h>
#include <stdlib.h>
void* operator new (size_t sz) throw() {
printf("global operator new\n");
return 0;
}
int main(int ac, char* av[]) {
struct newtest {
static void* operator new (size_t sz) throw() {
printf("newtest operator new\n");
return 0;
}
void dotest() {
char* a = new char;
printf("a = %p\n", a);
}
};
newtest t;
t.dotest();
newtest* t2 = new newtest;
};
実行結果
global operator new
a = (nil)
newtest operator new
* 参照型のメンバをもつクラスのコンテナとソート [#j00f0661]
** 参照型のインスタンスをもつクラスは、通常だとvector等の...
// 参照型のインスタスをもつクラス
struct Hoge {
int& instance_;
Hoge(int& i) : instance_(i) {}
Hoge(const Hoge& h) : instance_(h.instance_) {}
bool operator < (const Hoge& h) const { return instan...
};
std::vectorに入れてみる
std::vector<Hoge> vectorhoge;
int h1 = 1;
vectorhoge.push_back(h); // コンパイルエラー
operator =がないとvector::push_backはできない
listならOK
std::list<Hoge> listhoge;
int h1 = 1;
listhoge.push_back(h); // OK
** vectorに格納可能なリファレンスをもつクラスの定義 [#vea...
- vectorに格納(push_back, back_insert_iteratorなど)には、...
- リファレンス型の変数は、リファレンス情報の更新はできな...
*** 禁断の技その1 [#m5f8dfc7]
Hoge operator = (const Hoge& h) {
memcpy(this, &h, sizeof(Hoge));
return *this;
}
+ thisのデストラクタが呼ばれないで破棄される
+ オブジェクトのバイナリーコピーは非常に危険なのでダメ
*** 禁断の技その2 [#f178b88a]
Hoge operator = (const Hoge& h) {
this->~Hoge();
new (this) Hoge(h);
return *this;
}
+ いちおう、言語的には安全。
+ ハーブ・サッターさんは絶対に使うなと警告している方法
+ コピーコンストラクタとデストラクタで例外を投げないこと...
+ スレッドセーフでもない。シングルスレッド限定。
+ 自己代入の処理も必要
+ 欠点は多いけど、これでvectorに対する要素の追加やsortが...
*** コードの例 [#s7418473]
#include <cstdio>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
// 参照を持つクラスのswap
namespace {
struct Hoge {
int& instance_;
Hoge(int& i) : instance_(i)
{}
Hoge(const Hoge& h) : instance_(h.instance_) {}
// コピーコンストラクタとnewの第二構文を使った初期化...
// 例外安全ではない。デストラクタ・コピーコンストラク
終了行:
#include(C++TipsMenu,notitle)
* 定数の定義と静的構造体テーブルを同時に作るマクロ [#b36e...
定数の定義をソースコード上で行う場合、定数の定義と値の定...
通常はこのように書きます。
#sh(cpp){{
enum EnumHoge { hoge, fuga, piyo };
struct HogeHoge {
EnumHoge id;
float value;
const char* name;
} const table[] = {
{ hoge, 1.0f, "hoge" },
{ fuga, 2.0f, "fuga" },
{ piyo, 3.0f, "piyo" },
};
}}
enumの定義と構造体の定義が冗長で、名前の文字列の定義も冗...
しかし、魂を悪魔(#define)に売り渡せば、一発で記述できます。
#sh(c){{
// ここで定数を定義する(冗長でない単一の記載で済ませる)
#define LIST \
DEF(hoge, 1.0f), \
DEF(fuga, 2.0f), \
DEF(piyo, 3.0f)
// enumの生成
#undef DEF
#define DEF(a, b) a
enum EnumHoge { LIST };
// 構造体の生成
#undef DEF
#define DEF(a, b) {a, b, #a}
struct HogeHoge {
EnumHoge id;
float value;
const char* name;
} const table[] = { LIST };
}}
使用例
#sh(cpp){{
#include <stdio.h>
int main(int ac, char*av []) {
for (size_t n = 0; n < sizeof(table)/sizeof(HogeHoge);...
printf("table[%d] = id:%d value:%f name='%s'\n", n, ...
}
}
}}
結果
table[0] = id:0 value:1.000000 name='hoge'
table[1] = id:1 value:2.000000 name='gufa'
table[2] = id:2 value:3.000000 name='piyo'
ideone: http://ideone.com/HEIsAa#view_edit_box
* コンテナに対して、pushとpush_backを自動判別して追加する...
#sh(cpp){{
// decltypeを使ってコンテナに要素を追加する
// push_back()を持っている場合 ...
template <typename CT, typename VT>
inline auto push_to_container(CT& container, VT&& val, ...
{
return container.push_back(val);
}
// push()がある場合 ...
template <typename CT, typename VT>
inline auto push_to_container(CT& container, VT&& val) ...
{
return container.push(val);
}
}}
使用例
#sh(c){{
std::vector<int> hoge;
std::priority_queue<int> fuga;
...
push_to_container(hoge, 1); // hoge.push_back(1)が呼ばれる
push_to_container(fuga, 1); // fuga.push(1)が呼ばれる
}}
参考にしたページ
[[メンバー関数の存在を確かめる方法>http://codelogy.org/ar...
* VC++でイテレーターを高速化する [#xa008aee]
VC++では、イテレーターの範囲チェックが行われており、安全...
以下の定義を行うことで、範囲チェックを無効にできます。([[...
#define _SECURE_SCL 0
ちなみに、以下の設定で範囲チェックが有効になります。
#define _SECURE_SCL_1
#define _HAS_ITERATOR_DEBUGGING 1
* boost mpl map for_each覚え書き [#vd3ad1a2]
boost::mplのvectorやmapをfor_eachするサンプル。
mapのkeyだけ回すmap_keysのようなフィルタの例も作ってみま...
#sh(cpp){{
#include <iostream>
#include <vector>
#include <string>
#include <typeinfo>
#include <boost/mpl/list.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/key_type.hpp>
using namespace boost;
using namespace std;
struct Disp {
template <class Type>
void operator()(const Type&) const {
cout << typeid(Type).name() << endl;
}
template <typename K, typename V>
void operator()(const mpl::pair<K,V>&) const {
cout << typeid(K).name() << "," << typeid(V).nam...
}
} disp;
int main()
{
typedef mpl::list<int, std::string, char, std::vecto...
typedef mpl::map<mpl::pair<int,char>, mpl::pair<int,...
cout << "mpl list test" << endl;
mpl::for_each<tl>(disp);
cout << "mpl map test" << endl;
mpl::for_each<t2>(disp);
cout << "mpl map key_type test" << endl;
mpl::for_each<t2, mpl::lambda<mpl::key_type<t2, mpl:...
cout << "finish" << endl;
return 0;
}
}}
cpp_akiraさんのページにあったサンプルにmapを足してみまし...
http://ideone.com/rrk1ZY
* enumをコンテナのように扱う [#m6e894fd]
http://stackoverflow.com/questions/1390703/enumerate-over...
* http://ideone.com/J6ThVM [#h9126ac3]
* 普通の配列をboost:arrayに化けさせる [#wd8b9f45]
配列をboost::arrayやstd::vectorに置き換えてしまえばよいの...
既存の配列をboost::arrayに見せかけるツールを作りました。
template <typename T, size_t N>
inline boost::array<T,N>& to_array(T(&ar)[N]) {
return *reinterpret_cast<boost::array<T,N>*>(&ar...
}
template <typename T, size_t N>
inline const boost::array<T,N>& to_array(const T(&ar)[N]...
return *reinterpret_cast<const boost::array<T,N>...
}
to_array(<配列変数>); で、boost::array<型,サイズ> に変換...
これで、生の配列変数に対して、iteratorとか、size()とか、s...
ideone: http://ideone.com/oi43Mo
* 静的な文字列リテラルは、同名のものは同じアドレスを示す ...
プログラム中に"hoge"のように記載する文字列リテラルは、リ...
それを利用して、静的リテラルのアドレスをハッシュ値として...
#include <iostream>
const char* s1 = "hoge";
const char* s2 = "hoge";
int main(int ac, char*av[]) {
const char* s3 = "hoge";
std::cout << "s1 == s2 : " << (s1 == s2) << std::en...
std::cout << "s1 == s3 : " << (s1 == s3) << std::en...
std::cout << "s1 == 'hoge' : " << (s1 == "hoge") << std...
}
output
s1 == s2 : 1
s1 == s3 : 1
s1 == 'hoge' : 1
http://ideone.com/fJz5e
* 整数型配列の初期化 [#e87c5d4b]
クラスインスタンスの整数型配列をゼロで初期化するには、初...
before
class Hoge {
int a[10];
hoge() {
memset(&a[0], 0, sizeof(a));
}
}:
after
class Hoge {
int a[10];
hoge() : a() {
}
};
http://ideone.com/E3rEc
* 多重継承したクラスをnewの配置構文で確保したときの落とし...
多重継承したクラスのポインタは、親クラスのポインタにキャ...
class C : public A, public B {...}
C* c = new C;
assert((A*)c == (B*)c); // assertで停止
ポインタの値で比較するときは注意が必要。
同じ理由で、newの配置構文でクラスインスタンスを確保した場...
class C : public A, public B {...}
void* buffer = malloc(sizeof(C));
C* c = new(buffer) C;
B* b = c; // B*に代入
b->~B(); // ~B()がvirtualならば、デストラクタはA,Cとも...
free(b); // bの値はbufferと異なるので死にます
↓ ideone.comでのサンプル~
http://ideone.com/LdCNi
* == true で比較してはいけない理由 [#jcd6c4c2]
if文で値をbooleanとして比較するとき、trueと==で比較すると...
※ C++ では、intとbool値と比較しても、左辺値に対して暗黙の...
#include <stdio.h>
int main(int ac, char* av[]) {
int a = 2;
if (a) printf("a is true\n"); else printf("...
if (a == true) printf("a is true\n"); else printf("...
if (a != false) printf("a is true\n"); else printf("...
if (static_cast<bool>(a) == true)
printf("a is true\n"); else printf("...
return 0;
}
結果
a is true
a is false
a is true
a is true
"a == true" で比較したときだけ、結果が異なる。
http://ideone.com/UbvzC
* 仮想関数の部分オーバーライドについて [#wc903ad4]
class Base {
public:
virtual void hoge() = 0;
virtual void hoge(int a) { printf("a=%d\n", a); }
};
class Sub : public Base {
public:
virtual void hoge() { printf("hoge\n"); }
};
このように仮想関数を部分的にオーバーライドした場合、警告...
回避するには、 class Subに、"using Base::hoge; "を加える...
本来なら同名のオーバーライドを避けるべきである。
http://stackoverflow.com/questions/2057823/issues-with-pa...
* #defineマクロとの戦い [#n3d01c1c]
#define hoge(x) HOGE(x)
などで、別名を無理やり定義されてしまっているのをすり抜け...
- 方法1~
(ns::function) のようにnamespace付きで()で囲む~
例
(std::printf)("hoge") ; // printfが#defineされていてもオ...
- 方法2~
関数名と引数リストの間に空の#defineを挟む~
例
#define FOO
printf FOO("hoge"); // printfが#defineされていてもオリジ...
** コード例 (http://ideone.com/S44K6) [#gaad9cff]
#include <stdio.h>
namespace foo {
void hoge(const char* const msg) { printf("small hoge : ...
void HOGE(const char* const msg) { printf("LARGE HOGE : ...
}
#define hoge(msg) HOGE(msg)
#define FOO
int main(int ac, char* av[]) {
foo::hoge("ns::function");
(foo::hoge)("(ns::function)");
foo::hoge FOO("ns::function FOO");
};
output
LARGE HOGE : ns::function
small hoge : (ns::function)
small hoge : ns::function FOO
* boost pool [#s2f524fb]
- boost poolには、pool, object_pool, singleton_poolの3種...
- pool
-- malloc/freeを行う
-- コンストラクタでサイズを指定
-- コンストラクタで指定サイズのメモリをアロケート/フリー...
-- 指定サイズのN倍も可能 (ordered)
-- orderedと通常がある。
- object_pool
-- クラスのインスタンスを生成/破棄する
-- orderedのみ
- singleton_pool
--サイズ別にシングルトンとして動作する。
--シングルトンとして使える。
--vectorなどSTLのコンテナのアロケーターとして使える
--メモリの解放にはpurge_memoryしかない。(全放棄)
** orderedとは [#vc6ee3bd]
- 必ずメモリアドレスが順番になる(連続する)
- orederdだと、破棄したメモリブロックの再利用はされない
- 解放するには、release_memoryを呼ぶ(アロケートブロックが...
-非orderedが一つでも混在していると、release_memoryができ...
- おそい
**通常版(非orederd) [#ha2b1cac]
-破棄したメモリブロックが再利用される
-release_memoryはできない
-全部破棄のpurge_memoryは可
-連続したメモリブロックを確保できない
*** ordered、非orderedともに一長一短で使いにくい [#r8f6db...
* オーバーライドした関数の戻り値は、基本クラスの定義の戻...
#include <stdio.h>
struct Base {
virtual Base* create() = 0; // create new instance
virtual Base* clone() = 0; // create and copy i...
virtual void print() = 0;
};
struct Sub : Base {
Sub() {}
Sub(const Sub& sub) {} // copy constructor
Sub* create() { return new Sub(); }
Sub* clone() { return new Sub(*this); }
void print() { printf("I am Sub\n"); }
};
int main(int ac, char* av[]) {
Base* base1 = Sub().create();
Base* base2 = base1->clone();
base2->print();
return 0;
}
- 実行結果~
http://t.co/ASDjAEvI
* boost:multiindexは便利 [#md6c228e]
http://d.hatena.ne.jp/faith_and_brave/20091126/1259226643
* virtualやポインタを使わず、サブクラスの生オブジェクトを...
// BaseClassのサブクラスをコンテナにいれるためのクラス
// このクラスを使うことで、ポインタを使わず動的ポリモ...
template <typename BaseClass, size_t MaxSize>
struct DynamicPolymorphism : BaseClass {
uint8_t body[MaxSize - sizeof(BaseClass)];
DynamicPolymorphism() : BaseClass() {}
DynamicPolymorphism(const DynamicPolymorphism& m)...
memcpy(body, m.body, sizeof(body));
}
template <typename SubClass>
DynamicPolymorphism(const SubClass& m) : BaseClas...
SubClass& self = reinterpret_cast<SubClass&>(...
self = m;
}
template <typename SubClass>
void operator = (const SubClass& m) {
SubClass& self = reinterpret_cast<SubClass&>(...
self = m;
}
template <typename SubClass>
operator SubClass& () { return reinterpret_cast<S...
};
※これでunionから開放されます
比較的サイズが小さいクラスを実体のままコンテナに格納する...
例
class Car {
int cylinders; /* 気筒数*/
int displacement; /* 排気量 */
};
class Track : public Car { int payload = 1000; } // 最...
class Bus : public Car { int maxPeoples = 30; } // 乗...
vector<Car> carList;
carList.push_back(Truck()); // NG TruckがCarでスライ...
carList.push_back(Bus()); // NG BusがCarでスライシン...
vector<Car*> carList2;
carList2.push_back(new Truck()); // OK Truckの情報も...
carList2.push_back(new Bus()); // OK maxPeoplesの情報...
ポインタを使えば解決するけど、小さいオブジェクトを全部new...
unionを使った解決方法
class AllCar {
enum Type { Truck, Bus };
Type type;
int cylinders;
int displacement;
union {
int payload;
int maxPeoples;
};
};
vector<AllCar> allCarList;
AllCar truck;
truck.type = AllCar::truck;
allCarList.push_back(truck);
DynamicPolymorphismを使った例
class Car {
enum Type { Truck, Bus };
Type type;
int cylinders; /* 気筒数*/ int displacement; /* 排気...
};
class Track : public Car { int payload = 1000; } // 最...
class Bus : public Car { int maxPeoples = 30; } // 乗...
typedef DynamicPolymorphism<Car, max(sizeof(Truck), si...
vector<AllCars> allCars;
allCars.push_back(Truck()); // AllCarsは継承クラスの...
allCars.push_back(Bus());
Truck& t = allCars.front(); // DynamicPolymorphismのオ...
Bus& t = allCars[1];
* operator new の効力範囲 [#tdb48b30]
#include <stdio.h>
#include <stdlib.h>
void* operator new (size_t sz) throw() {
printf("global operator new\n");
return 0;
}
int main(int ac, char* av[]) {
struct newtest {
static void* operator new (size_t sz) throw() {
printf("newtest operator new\n");
return 0;
}
void dotest() {
char* a = new char;
printf("a = %p\n", a);
}
};
newtest t;
t.dotest();
newtest* t2 = new newtest;
};
実行結果
global operator new
a = (nil)
newtest operator new
* 参照型のメンバをもつクラスのコンテナとソート [#j00f0661]
** 参照型のインスタンスをもつクラスは、通常だとvector等の...
// 参照型のインスタスをもつクラス
struct Hoge {
int& instance_;
Hoge(int& i) : instance_(i) {}
Hoge(const Hoge& h) : instance_(h.instance_) {}
bool operator < (const Hoge& h) const { return instan...
};
std::vectorに入れてみる
std::vector<Hoge> vectorhoge;
int h1 = 1;
vectorhoge.push_back(h); // コンパイルエラー
operator =がないとvector::push_backはできない
listならOK
std::list<Hoge> listhoge;
int h1 = 1;
listhoge.push_back(h); // OK
** vectorに格納可能なリファレンスをもつクラスの定義 [#vea...
- vectorに格納(push_back, back_insert_iteratorなど)には、...
- リファレンス型の変数は、リファレンス情報の更新はできな...
*** 禁断の技その1 [#m5f8dfc7]
Hoge operator = (const Hoge& h) {
memcpy(this, &h, sizeof(Hoge));
return *this;
}
+ thisのデストラクタが呼ばれないで破棄される
+ オブジェクトのバイナリーコピーは非常に危険なのでダメ
*** 禁断の技その2 [#f178b88a]
Hoge operator = (const Hoge& h) {
this->~Hoge();
new (this) Hoge(h);
return *this;
}
+ いちおう、言語的には安全。
+ ハーブ・サッターさんは絶対に使うなと警告している方法
+ コピーコンストラクタとデストラクタで例外を投げないこと...
+ スレッドセーフでもない。シングルスレッド限定。
+ 自己代入の処理も必要
+ 欠点は多いけど、これでvectorに対する要素の追加やsortが...
*** コードの例 [#s7418473]
#include <cstdio>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
// 参照を持つクラスのswap
namespace {
struct Hoge {
int& instance_;
Hoge(int& i) : instance_(i)
{}
Hoge(const Hoge& h) : instance_(h.instance_) {}
// コピーコンストラクタとnewの第二構文を使った初期化...
// 例外安全ではない。デストラクタ・コピーコンストラク
ページ名: