No Such Blog or Diary

«Prev || 1 | 2 | 3 |...| 1207 | 1208 | 1209 |...| 1276 | 1277 | 1278 || Next»

修論

丸々一章分と数節抜けてるけどとりあえずコメントもらいに投げてみる.数パターンある定義のどれで話を進めるか... とりあえず全部書いとくかな.

冬眠モード

最近眠すぎる... 飯作って食ったら眠くなった.寝る. 計算片付かず...

計算

のつじつまが合わない場合があるので少々頭を使わねば.定義が汚くなるので微妙だなぁ.

PCの電源をつけるたびに

グラフィックカードの電源が足りないのでチップのパフォーマンスを落としますと警告がでるようになってしまった.400Wだし買ってから一年半たったのでそろそろ要領不足になったのだろうか(12Vが)? Seasonic の 500W か 600Wにしたいところだけど,これらも下手すると爆発する不具合でてるらしいし.白狼でもいいかと思うがこっちはケーブルが硬かったりするし.もうしばらく様子見かなと.とりあえず起動しなくなる前にバックアップだけはとっておくか.

サブクラス判定

ちゃんと探せば STL や Boost に is_convertible と is_base とかがあった.肝を抜き出してみるとこんなもん.

#include <iostream>
using namespace std;
 
template<typename From, typename To>
struct isConvertible {
    static char test(To);
    static long test(...); // variable argument で逃げる
    static From from();
    static const bool value = sizeof(test(from())) == 1;
};
 
class A {};
class B : public A {};
 
int main(int argc, char *argv[])
{
    cout << isConvertible<A, B>::value << endl;
    cout << isConvertible<B, A>::value << endl;
    return 0;
}

test 関数の呼び出しで From から To に変換できる場合は test(To) が選択され,sizeof(test(from())) = 1 となるので value = true となる.そうでなければ test(...) が選択され sizeof(test(from())) != 1 で value = false と.variable arguments 使って型指定をなくせるのに気づかなかった...

もう少し高度なトリックを使うと次の is_base のメイン部分になるらしい.

#include <iostream>
using namespace std;
 
template <typename Super, typename Sub>
struct isSuperclasOf {
    template<typename T>
    static char test(Sub &, T);    
    static long test(Super &, int);
    struct C {
        operator Super &() const;
        operator Sub &();
    };
    static const bool value = sizeof(test(C(), 0)) == 1;
};
 
class A {};
class B : public A {};
 
int main(int argc, char *argv[])
{
    cout << isSuperclasOf<A, B>::value << endl;
    cout << isSuperclasOf<B, A>::value << endl;
    return 0;
}

http://tinyurl.com/502fhttp://tinyurl.com/6jvyq に原理が書いてある.結局はある変換系列が他の変換系列の prefix になっているなら短い型変換が優先で,テンプレート有り関数とテンプレート無し関数では無い関数が優先であることを使っているらしい.Super が Sub の親クラスの場合,test(Super&, int) が呼ばれるには C → Sub → Super の変換列をとり( C → C const → Super 側は無視される),一方で test(Sub&, int) は C → Sub という変換列となる.このとき, C → Sub が C → Sub → Super の prefix になっているので test(Sub&, int) が選択される.よって,sizeof(test(C(), 0)) が 1 になるので value が true になる.Super が Sub の親クラスで無い場合は,test(Super&, int) が呼ばれるには C → C const → Super という変換列となり,これは C → Sub に吸収されないので test(Super&, int) と test(Sub&, int) の可能性がある.しかし,test(Sub&, int) に関してはテンプレートの instantiation があるので test(Super&, int) が選択される.よって,この場合は sizeof(test(C(), 0)) が 1 でないので value が false になる.

よくかんがえるもんだなぁ.

C++ であるクラスを継承しているかどうかの判定って

できるかなぁと.

#include <iostream>
using namespace std;
 
template <typename E>
class Eq {
    virtual bool operator==(const E& e) const = 0;
};
 
class Int : public Eq <Int> {
public:
    int num;
    bool operator==(const Int& e) const { return this->num == e.num; }
    Int(int num) { this->num = num; }
};
 
template <typename A>
struct HasEq {
    enum {val = 0};
};
 
template <typename A>
struct HasEq< Eq<A> > {
    enum {val = 1};
};
 
int main(int argc, char *argv[])
{
    cout << HasEq<Int>::val << endl;
    return 0;
}

このコードの出力が 1 になってほしいと.このコードでは 0 を出力するほうに実体化されるので,これを避けたい.キャストを入れて 0 出力側で実体化を失敗させればいいのかな?

«Prev || 1 | 2 | 3 |...| 1207 | 1208 | 1209 |...| 1276 | 1277 | 1278 || Next»
Search
Feeds

Page Top