ファイルパス周りの用語が解らなくなりはじめて死亡

やだ恥ずかしい……

パス例 日本語圏 英語圏
notepad.exe
.\notepad.exe
..\notepad.exe
相対パス relative path
\windows\notepad.exe absolute path
c:\windows\notepad.exe 絶対パス / フルパス fully qualified path (完全修飾パス)

…で、良いのかしら…?

ここで、完全じゃない修飾パス "qualified path" はあるのかしら? とかいう疑問もあるんですが、ドキュメントによっては次のように書かれているのがありまして…

Converts a relative or unqualified path name to a fully qualified path name.

PathResolve function | Microsoft Docs

"unqualified path" とはなんぞと(ぉ orz

書き方からし相対パスとは別物なんじゃないかと思うんですが… 良くわからんぜ…

ファイル名に数字が入ったディレクトリをExplorerで名前ソートで表示した場合、ただの文字列比較じゃない感じでソートされるヤツの文字列比較関数があったァァァァ!!!

StrCmpLogicalW

へぇえええ!!

しかしなんというか、こんな関数よく実装したよねって思う。超面倒な気がするんだけど(ぉ

(皆さんご周知の事ではありますが、偶には思い出すべきです故にあえて言いますが)VC6は糞

#include <iostream>

template<typename T>
class A
{
public:

    A()
    {
        std::cout << "A()" << std::endl;
    }

    A(const A<T>& t)
    {
        std::cout << "A<T>()" << std::endl;
    }

    template<typename U>
    A(const A<U>& u)
    {
        std::cout << "A<U>()" << std::endl;
    }

};

int main()
{
    A<int>  int1;
    A<int>  int2(int1);
    A<long> long_(int1);

    return 0;
}
// VC2005
A()
A<T>()
A<U>()

まぁ、当然ですね。

これをまだどこかの中小企業で明らかに現役で使わされているであろう VC++6.0 でコンパイルすると…

>cl /EHsc a.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.

a.cpp
a.cpp(21) : error C2535: '__thiscall A<U>::A<U>(const class A<U> &)' : メンバ関数は、すでに定義または宣言されています。
        a.cpp(15) : 'A<T>::A<T>' の宣言を確認してください。
        a.cpp(26) : コンパイルされたクラスのテンプレートのインスタンス化 'A<T>' の参照を確認してください
a.cpp(31) : error C2668: 'A<int>::A<int>' : オーバーロード関数の呼び出しを解決することができません。(新機能 ; ヘルプを参照)

どうやら A(A<T>& t) と A(A<U>& u) がカブっている扱いするようです。

まぁ50歩くらい譲れば気持ちは分からんでもないので、A(A<T>& t) の方を消すとコンパイルが通ります。 A int2(int1); が A(A<U>& t) の方に解決されて、上手くやってくれるのでしょう。

// VC6
A()
A<U>()
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄」
―――――――――――――‐┬┘
                        |
       ____.____    |
     |        |        |   | 
     |        | ∧_∧ |   | 
     |        |( ´∀`)つ ミ | 
     |        |/ ⊃  ノ |   |
        ̄ ̄ ̄ ̄' ̄ ̄ ̄ ̄    |    ミ[VC6]


デフォルトコピーコンストラクタ発動してんじゃねーよ!! コピコン書いただろ! ダメって言っただろ!! なんでコンパイラ自身が自動で用意したのはOKなんだよコンナロー!!

というわけで VC6は糞

で、思いつきでコード弄くった

ホント思いつきで、A<U>() の ctor に "void* vc6_is_kuso = NULL" を追加してみました。

#include <iostream>

template<typename T>
class A
{
public:

    A()
    {
        std::cout << "A()" << std::endl;
    }

    A(const A<T>& t)
    {
        std::cout << "A<T>()" << std::endl;
    }

    template<typename U>
    A(const A<U>& u, void* vc6_is_kuso = NULL)
    {
        std::cout << "A<U>()" << std::endl;
    }

};

int main()
{
    A<int>  int1;
    A<int>  int2(int1);
    A<long> long_(int1);

    return 0;
}
// vc6
>cl /EHsc a.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.

a.cpp
Microsoft (R) Incremental Linker Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

/out:a.exe
a.obj

>a
A()
A<T>()
A<U>()
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄」
―――――――――――――‐┬┘
                        |
       ____.____    |
     |        |        |   | 
     |        | ∧_∧ |   | 
     |        |( ´∀`)つ ミ | 
     |        |/ ⊃  ノ |   |
        ̄ ̄ ̄ ̄' ̄ ̄ ̄ ̄    |    ミ[VC6] ミ[VB6]

PathQuoteSpaces() の戻り値の型がモノによって異なっていて死亡

// VC6
LWSTDAPI_(void)     PathQuoteSpacesA(LPSTR lpsz);
LWSTDAPI_(void)     PathQuoteSpacesW(LPWSTR lpsz);
// VC2003
LWSTDAPI_(void)     PathQuoteSpacesA(LPSTR lpsz);
LWSTDAPI_(void)     PathQuoteSpacesW(LPWSTR lpsz);
// VC2005
LWSTDAPI_(void)     PathQuoteSpacesA(LPSTR lpsz);
LWSTDAPI_(void)     PathQuoteSpacesW(LPWSTR lpsz);
// VC2010 // "BOOL" …だと…?
LWSTDAPI_(BOOL)     PathQuoteSpacesA(__inout_ecount(MAX_PATH) LPSTR lpsz);
LWSTDAPI_(BOOL)     PathQuoteSpacesW(__inout_ecount(MAX_PATH) LPWSTR lpsz);

えぇ…? ('A`)

http://ir9.jp/hd16/hd0627_00.png
http://ir9.jp/hd16/hd0627_01.png
http://ir9.jp/hd16/hd0627_02.png
http://ir9.jp/hd16/hd0627_03.png

(順に VC6/2003/2005/2010)




ちなみに、Web上のMSDN では 戻り値が BOOL だったりしますが、VC6/2003/2005 の ヘルプでは void となってたりします (↓順に VC6/2003/2005 の MSDN ヘルプ)

http://ir9.jp/hd16/hd0627_04.png
http://ir9.jp/hd16/hd0627_05.png
http://ir9.jp/hd16/hd0627_06.png

で、戻り値の型を環境によって変えちゃって良いんですかね…? 特に void → BOOL で戻り値が「無し」から「なんか4byteある」の状態になるので、スタックぶっ壊れないの? と思ってみたりはしますが、__stdcall → 呼び出し先の関数がスタックの調整を行うので、変わっても問題無い感じなんですかね…? 個人レベルではめっちゃおっかない感いっぱいなんですけど(ぉ

とりあえず何が言いたいかというと、おのれ Micros●ft!!!!

追記

PathUnquoteSpaces() も似たような問題がありました

Web上じゃ void なのに、SDKの定義は BOOL … どういう事だってばよ…!?

if() のカッコ内で変数定義出来なくて死亡

struct A
{
	A(){}
	A(int dummy){}

	operator bool () const {
		return true;
	}
};

if(int n = 1)
{	// 当然OK

}

if(A a(1))
{	// C2059

}

if(A a)
{	// C2059

}

if(A a = A(1))
{	// OK

}

へー

…真ん中もOKになりませんかね(ぉ

自動プロパティの暗黙具合に死亡

class Rozen
{
    public string Name
    {
        get;
        set;
    }
};

みたいな感じで、C#で自動プロパティ作った後に「setter で来る value をトレスしたいな!」なんて思い始めた際に積む感じですかねやはり…? 自動プロパティが生成する暗黙のフィールドあたりに value を代入できないですよね… 暗黙だし

class Rozen
{
    public string Name
    {
        get;
        set
        {
            Debug.Print("Rozen::Name={0}", value);
            ...??? = value; // 死ぬ死んだ
        }
    }
};

自前で値保存用のフィールド設けるしかないですよねぇ… プロパティの数増えてきたも、全部自前で「プロパティと対となるフィールド」を作らないと行けないですよね…。 setter 呼ばれた際に トレスじゃなくて event を callback する機能追加ーなんて時も同様ですよねぇ…

ですよねぇ…

ですよねぇ……

ですよねぇ………

あああ

クラス変数初期化時に他のクラスメンバが見つからなくて死亡

にわかpython屋のわし、詰まる。

#python3

class A :

    def set(self, type, value) :
        A.FUNC_MAP[type](self, value)
    
    def _setSearch(self, s) :
        self.search = s
    
    def _setTitle(self, s) :
        self.title = s

    FUNC_MAP = {
        "search" : A._setSearch,    # NameError: name 'A' is not defined
        "title"  : A._setTitle,
    }

a = A()
a.set("title", "たいとる")
a.set("search", "検索語")

print(a.title)
print(a.search)

A::set() でメンバ変数をセット、セットする先の変数も関数の引数の文字列で dispatch する…って事をやりたくて、キーワードに対する関数マップを作りました。 が、A::_setSearch が見つから無ぇ! なんだとメガトロン!?

…と、一睡した結果こうなりました。

#python3

class A :

    def set(self, type, value) :
        A.FUNC_MAP[type](self, value)
    
    def _setSearch(self, s) :
        self.search = s
    
    def _setTitle(self, s) :
        self.title = s

    FUNC_MAP = {
        "search" : _setSearch,  # クラス名修飾要らない
        "title"  : _setTitle,
    }

a = A()
a.set("title", "たいとる")
a.set("search", "検索語")

print(a.title)
print(a.search)

嘘だと言ってよバーニィ! クラス変数初期化時はクラス名が不要だったなんて……


class Kashira :

    clazz = 10
    
    def bar(self) :
        print(Kashira.tamagoyaki)

とか、メンバ関数内からであってもクラス変数参照する際はクラス名を修飾しないとアカンので、すっかり付ける事しか頭に無かったわ…

Nameエラーの内容が「"A" なんか知らねぇよ。糞して寝ろ。二度と来んな」って言ってるって事は、つまる所クラス変数初期化時にまだ class A が存在しないって事なんですね。 おそらく初期化中だから。 なるほど…



あ、この程度なら dict に lambda 直接突っ込めばいいじゃんというツッコミは無しでお願いします(ぉ