Boost.勉強会/Boost.懇親会 雑記

いまさらですが、忘れないうちに。

  • お二人にサインもらった
  • Cryoliteさん、uskzさん、道化師さん、ir9さんと話せた
  • shinhさんが隣に居たけど声かけられなかった、残念
  • 参加者の年齢層低め、自分が上のほうでした
  • lexical_castは数値型以外にも使えます!
  • Boost.Asioをアジオと呼ぶとASIOと区別がつかないのでアシオかエイシオと呼びたいです。あとエイシンクね。
  • ノートPCを持ち運べるバッグを買わねば!帰省前に気づいて助かった。
  • 次回までにTwitterアカウントを用意しよう。もうIRCは古いみたい。
  • D4は4、5回通信できなくなって再起動、1回ブルースクリーン。いまいち使えない。
  • 次は発表したい!けどパワポは書いたことがない人。
  • google:Macは繋がるのにWinは繋がらない

文字型三種

「charでなく、signed char/unsigned charをストリームに出力した場合何がでるんだっけ?」
Boost.懇親会でCryoliteさんと話していて、宿題にしていた疑問です。
何か罠があっていつもキャストしてから出力していたのですが、思い出せず。
帰ってすぐ確認しました。

#include <iostream>

int main()
{
    std::cout << 'c' << std::endl;
    std::cout << static_cast<signed char>('s') << std::endl;
    std::cout << static_cast<unsigned char>('u') << std::endl;
    std::cout << L'w' << std::endl;

    std::cout << "char" << std::endl;
    std::cout << reinterpret_cast<const signed char*>("signed char") << std::endl;
    std::cout << reinterpret_cast<const unsigned char*>("unsigned char") << std::endl;
    std::cout << L"wchar_t" << std::endl;

    std::wcout << 'c' << std::endl;
    std::wcout << static_cast<signed char>('s') << std::endl;
    std::wcout << static_cast<unsigned char>('u') << std::endl;
    std::wcout << L'w' << std::endl;

    std::wcout << "char" << std::endl;
    std::wcout << reinterpret_cast<const signed char*>("signed char") << std::endl;
    std::wcout << reinterpret_cast<const unsigned char*>("unsigned char") << std::endl;
    std::wcout << L"wchar_t" << std::endl;
}

実行結果

c
s
u
119
char
signed char
unsigned char
00000001400053B8
c
115
117
w
char
00000001400053D0
00000001400053E0
wchar_t

なんかExceptional C++辺りで似た問題を見た気もしますが、signed/unsignedが付いても結果が変わりませんでした。
8桁の十六進になっている箇所はvoid*として出力された箇所です。(VC++9.0/x64)
3桁の十進はintとして出力された箇所です。

オーバーロードも三種だと思っていたのにもっとありました。

// c
template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out, charT c);

// widen(c)
template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out, char c);

// c
template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, char c);

// (char)c
template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, signed char c);

// (char)c
template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, unsigned char c);

ポインタ版も同じだけあります。
この結果から考えると、自分がキャストしていたのは、

void print_ui8(boost::uint8_t n)
{
    // 文字列でなく、8ビットの数値として出力したい
    std::cout << static_cast<unsigned>(n) << std::endl;
}

みたいなパターンですね。

続・ナゾ042

例のナゾですが、いつの間にか分かりにくい場所にお詫びが載っていました。
http://www.layton.jp/majin/nazo042.html
この修正に合わせるには、前のコードの360.0fを足している箇所を消せばよいです。
ただ、修正後のナゾだとヒントと数が合わなくなるので、やっぱり変です。
制作者が短針の動きを忘れていた可能性大です。
まぁ、答えを書かずに正解へ導くための配慮と、好意的に解釈しておきましょう。

ASIO4ALL on x64

Windows 7 (x64) にASIO4ALL (x64)をインストールしたのですが、IASIO::setSampleRate()が必ず失敗します。
IASIO::setSampleRate()しなければ動くようで、どうもdouble引数の受け渡しがうまくいっていない模様。
Winampのout_asio(x64).dllも動かないので自分のコードの間違いではなさそうです。
また、32ビットなら動きます。

typedef long ASIOError;
typedef double ASIOSampleRate;

struct IASIO : public IUnknown
{
    // ...
    virtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0;
    // ...
};

COMなのに__stdcall使ってないのでx86ではVC++以外のコンパイラで困りましたが、
x64では呼び出し規約が一つ*1なので問題ありません。
x64呼び出し規約では、thisポインタがRCX、sampleRateがxmm1で渡されるはずです。
ところがデバッガで追っていくとxmm1は一切参照せず、代わりにxmm0を見ているようでした。
試しにバイナリエディタでxmm0→xmm1に書き換えて試したところ動いてしまいました。(Winampでも!)
一応パッチ内容を貼っておきます。

asio4all64.dll (MD5: 3e27e83063cd64a25f914e7ef556112c)
0x000056CD: C0 -> C1
0x000057CF: C0 -> C1

うーむ、こんな対応でいいんでしょうか、、、。

*1:gccは使うレジスタが違う模様