syghの新フラグメント置き場

プログラミングTipsやコード断片の保管場所です。お絵描きもときどき載せます。

C++でstaticクラス

C#には「staticメンバーだけを定義して、実体化は許可しない」ようなクラスを定義する手段があります。

public static class MyHelper
{
  public static int Add(int x, int y)
  { return x + y; }
}

staticクラスは状態を管理しない純粋ヘルパーを定義するのに便利です。代表的な例でいうと、System.Mathクラスが挙げられます。
なお、staticクラスからはサブクラスを派生させることもできません。

C++/CLIおよびC++/CXでは以下のように書くことでC#のstaticクラス相当を記述できます。

public ref class MyHelper abstract sealed
{
public:
  static int Add(int x, int y)
  { return x + y; }
};

しかし、従来の標準C++では、staticクラスを記述する文法は直接サポートされていません。
せいぜいできることと言えば、以下のようにデフォルトコンストラクタとデストラクタを隠ぺいして実体化を禁止するくらいしかなく、C#と比べて分かりやすさはともかく美しさに欠けます。
また、派生を禁止するにはC++11以降のfinalキーワードを使う以外ありません。

class MyHelper final
{
private:
  MyHelper() {}
  ~MyHelper() {}
public:
  static int Add(int x, int y)
  { return x + y; }
};

MSVCにはネイティブC++でもabstractキーワードを使えるように言語拡張が施されているので、abstract sealedまたはabstract finalを指定することでstaticクラスを記述することができるのですが、Clangなどでは使えません。移植性の高いコードを書きたい場合は注意が必要です。

無修正画像のリクエストを受けたとき、どう対処・回答すべきか

三次元のお話

自分には縁のない話ですが、一般論として。
恋人に「裸の自撮り写真を送ってくれ」「他の誰にも見せたりしないから」などとお願いされても、はっきりと拒絶すべきですね。そしてそんなことを臆面もなく言ってくるリテラシーの低い野郎とは即刻別れるべきです。将来表を歩けなくなってもかまわないなら話は別ですが。
つい忘れがちですが、インターネットは全世界につながっています。一見プライバシーが保護されているように見えるメールも例外ではありません。いまや画像はもちろん動画でさえ、誰でも簡単にデータをアップロード・共有できますが、同時にクリックひとつで全世界に公開できてしまいます。ネット上に裸の画像をばらまかれて永久に消せない汚点を残すような、いわゆるリベンジポルノにつながるだけでなく、刑法175条のわいせつ物頒布罪(わいせつ電磁的記録記録媒体頒布罪*1)に問われる可能性もあります。

二次元のお話

では、二次元のイラストや漫画に関してはどうでしょうか?
やはり日本国内では三次元同様「無修正はわいせつ物とみなされてアウト」になります。
pixivなどのSNSサイトで、R18カテゴリーのエッチなイラストや漫画をアップロードされている方は注意が必要です(自分を含めて)。
自分で撮った写真や自分で描いた絵などを、自分だけがアクセスできる個人端末のハードディスクや光学メディアに保存すること、つまり無修正の元データの単純所持自体には法律的に問題ありません。そうでないと作品の創作や制作ができませんので。もちろん児童ポルノは除きます。児童ポルノは無修正だろうが修正済みだろうが、単純所持ですらアウトです*2児童ポルノ、ゼッタイダメ。

しかし、たとえ自作であろうとも、無修正画像を不特定多数に公開・譲渡するとなると、前述の刑法175条に抵触します。公開対象の多い少ないにかかわらず、メールやSNSのファイル添付、ストレージサービスなど、共有目的でインターネットにアップロードすること自体が危険だと考えてください*3
某ポルノサイトでは海外のサーバーに無修正データをアップロードすることで日本の法律を潜り抜けようとしていますが、限りなく黒に近いグレーだということもお忘れなく。

よって、他人から「○○の無修正画像をもらえませんか?」などというリクエストを受けても、安易に譲渡してはいけません。

個人的意見

これは絵描きとしての個人的な意見ですが、せっかく描いたものに、モザイクやぼかし、ベタ/ホワイトで修正なんてしたくないんです。同人誌を発行するときや、SNSサイトに公開するときに、ときおり修正が弱いと指摘されることがあり、しぶしぶ手直ししていますが、内心では引っかかるものがあります。別にゾーニングができていればいいじゃないか。むやみに隠そうとするから逆におかしなことになるんです。むしろ修正したほうが余計にわいせつ感が増すと感じるのは自分だけではないはず。滑稽ですね。ゾーニングができていない(年齢詐称による抜け道があり、事実上誰でも閲覧できる)ことのほうがよほど問題です。

具体的に何をどの程度修正すれば「わいせつ物」とみなされないか、に関しても、法律で明確に定められているわけではありません。警察のさじ加減ひとつで決まってしまいます。修正は出版社・印刷会社・イベント主催者や創作者の自主規制でしかありません。でも捕まりたくはないので、安全側に自主規制せざるを得ない。ジレンマですね。その自主規制も年々強くなっているようで、業界全体が萎縮しているように感じられます。昔はゴールデンタイムに放送されるアニメでも乳首くらいは余裕だった*4というのに……

*1:「記録」が連呼されていますが、どうやら誤植ではなく法律上の正式名称らしいです。ややこしいですね。

*2:非実在青少年」とやらの話は、ここではツッコミません。あしからず。

*3:たとえ個人的なバックアップ目的だとしても、クラウドサーバーに無修正画像をアップロードするのは避けるべきです。

*4:昨今の深夜アニメの謎の光や自主規制マークは、円盤の購買意欲をそそるための差別化戦略でもあるのかもしれませんが。

Windows 10 1709/1803でキャレットの点滅が止まる

Windows 10 1709 (Fall Creators Update) には、エディットボックスなどのキャレット(縦棒のカーソル)の点滅が5秒程度で止まってしまうバグがあるようです。確かキャレットはシステムタイマーでOSが点滅させているはずですが、フォーカスしてから5秒くらい経過すると点滅が止まってしまいます。キャレットに独自の形状を使って自前で描画しているMIFESでも点滅が停止します。1703 (Creators Update) 以前ではこんな現象は発生していませんでした。1803にも同様のバグがあるようです。

キャレットの点滅は、現在のフォーカスがどのUI要素にあるのか、またアプリ(のUIスレッド)が生きているのかどうかを知ることのできる重要なインジケーターのひとつなので、これが止まってしまうとかなり困ります。この問題は、MFCアプリを開発していたときに気づきました。一瞬アプリ側のバグもしくは設計ミスかとも思いましたが、ありとあらゆるWin32アプリで発生するのでOS側に問題があることは確実です。

しかし、あろうことか窓の杜の某ライターは、キャレットの点滅が止まってしまうのを「仕様変更」だとうそぶいています。これは仕様変更じゃなくてただのお粗末なバグです。なぜ公式発表もないのに、れっきとしたメディアのライターがいい加減なことを書くのでしょうか。

さらに無理やり点滅を継続させるサードパーティ製ツールの紹介までしていますが、こんなくだらないツール作るヒマがあったらMSに不具合報告すべきですね。なんでも日曜大工でDIYすればいいってもんじゃないです。自動車の構造や計器に安全基準不適合の不具合や設計ミスがあったらリコール対象でしょう。不具合に気付いたら勝手に自分で改造して対応したり、その場しのぎの改造方法をユーザー間で共有したりするべきではなく、社会全体のことも考えて国土交通省に報告すべきです。ちなみにWindows 10ではエンドユーザーでもフィードバックHubで不具合報告できるので、おかしな動作に気がついたら個人でもどんどん報告すべきですが、多数の意見・要望が集まらない限りMSは動こうとしません。無視・黙殺されるのがオチです。

Windows 10の品質問題

Windows 10は特に従来のWin32デスクトップまわりの品質が明らかに低下しているように思われます。1709はGetPixel/SetPixel関数のパフォーマンスデグレードもやらかしやがったので、まったく良い印象がありません。1703は2018年10月でサポート期限が切れますが、1709はスキップして1803にすることも検討しています。
それにしても今のWindowsは、すでにある機能を破壊・劣化させてまで追加する価値のある機能など、なにひとつ提供できてないと思います。むしろ余計な新機能のほうがユーザーエクスペリエンスの邪魔をしているくらいです。Windows 7/8.1同様の快適性を得るために、いったいいくつの機能を無効化したか知れません。既存機能の破壊と劣化はApple同様、リリーススケジュールばかり優先して品質確保をおろそかにしているツケがまわってきているだけですが、頻繁な大型アップデートによる新機能追加なぞまったく望んでもいないユーザーが、なぜそこで不利益を被らなければならないのか。極めて疑問です。

FirefoxでGoogle検索結果から特定のサイトを除外する

安全・快適なインターネットライフのために、Google検索結果から不快・不正なサイト(NAVERまとめとか)は除外したいですよね。

Firefox Quantumより前のバージョンでは、「Hide Unwanted Results of Google Search」というアドオンを使っていました。このアドオンの素晴らしいところは、ワイルドカード正規表現で除外したいサイト・ページを柔軟に指定することができた点です。しかし、Quantum (v58以降) では仕様変更により、古いアドオンが使えなくなりました。「Hide Unwanted Results」はその後更新されておらず、Quantumに対応していないので非常に残念です。

Quantumに更新した後、現在は「Personal Blocklist (not by Google)」を使っています。もともとGoogle Chrome向けの公式アドオンとして公開されていた「Personal Blocklist (by Google)」を、Firefox向けに書き直したものだそうです。

ただ、残念ながらこのアドオンは「Hide Unwanted Results」と違い、ドメイン/ホスト単位でしか除外できません。たとえばQiita (qiita.com) から特定のユーザー*1のページだけを除外する、ということはできないわけです。

*1:Qiita自体は有用で参考になりますが、他のユーザーをバカにした不快なコメントを連発している傲慢なユーザーや、コメント欄でたびたびケンカ・炎上させているようなユーザーのページは検索結果にすら表示させたくないです。

Windowsセキュリティ認証とネットワークパスワード

Windowsで共有フォルダーにアクセスする場合、セキュリティ認証のためのパスワード入力を求められることがあります*1

しかし、PCを再起動/シャットダウンするなどして、ログオンセッションが終了すると、再度入力が必要になってしまいます。

コマンドプロンプトでセキュリティ認証を実行する場合、以下のようにnetコマンドを使うことができます。

net use \\<IPアドレスもしくはホスト名>\<共有名> /user:<ユーザー名> <パスワード>

再入力の手間を省く方法として、コマンドをバッチファイルに書き込んでおいて、バッチファイルをスタートアップに登録する手法もあるのですが、パスワードを平文でテキストファイルに書き込むのはセキュリティ上のリスクがありますね。

代わりに「資格情報マネージャー」(Credential Manager) を利用するとよさそうです。

www.mtecweb.com

Windows 10の場合もコントロールパネルからアクセスできます。

ちなみにTortoiseGitなどもWindowsのセキュリティ認証を使用しますが、あろうことか認証ダイアログで誤ったパスワードを入力してしまった場合でも、その誤ったパスワードが資格情報マネージャーに記録されてしまいます。以後、認証ダイアログが出ずに接続が延々と失敗し続けてしまう現象が発生します。誤ったパスワードを削除する場合、コントロールパネルの資格情報マネージャーから各情報セットを削除する必要があります。

*1:同一ユーザー名で同一パスワードの場合、パスワード入力なしに透過的にアクセスできます。

Visual C++コンポーネントの復旧

Visual Studio 2015 Update 3がインストールされているWindows 7 x64環境において、Python Tools for Visual Studioを2017年1月版に更新した後、Visual C++プロジェクトを含むソリューションファイルを開くと、

インストール コンポーネントがないため、プロジェクト 'XXX' を読み込めませんでした。修正するには、以下の選択をして Visual Studio セットアップを起動してください:
Install Visual C++ 2015 Tools for Windows Desktop

というエラーメッセージが出るようになりました。VC++プロジェクトは「利用不可」と表示されます。

しかし、Visual C++のプロジェクトテンプレート群はインストールされていて、Visual Studioのバージョン情報にもVisual C++コンポーネントは表示されます。どうやら、何らかのファイルが破損するなりして、VC++コンポーネントが正常に認識されていない模様。

[プログラムと機能]からVisual Studioのインストールウィザードを使って[修復]インストールしても改善しません。
[変更]インストールでコンポーネントのインストール状態をチェックしたところ、なぜか[プログラミング言語]→[Visual C++]配下のコンポーネントのチェックがすべて外れていました。

チェックを入れ直してインストールを実行すると、問題が解消されました。

一度「利用不可」状態になってしまったプロジェクトは、.suoファイルにアンロード状態が記録されてしまうようなので、コンテキストメニューから[プロジェクトの再読み込み]を実行して状態をリセットすればOK。

たぶんPython Toolsを更新したときに一部のVC++コンポーネントが勝手に削除されてしまったのだと思われます。ひどいバグですね。

Visual Studio 2015のコード整形機能のバグ

Visual Studioのコードエディターでは、C#コードを入力する際、ペースト時や閉じ中カッコ0x7Dあるいはセミコロン0x3Bを入力したタイミングなどで自動的にフォーマット(コード整形)が発動し、タブや空白などが自動調整されます。以前のバージョンのVisual Studioでは、C++コードでは明示的なフォーマット機能(ショートカット:Ctrl+K, Ctrl+F)のみをサポートしていましたが、Visual Studio 2015では、C++でもC#に近いオートフォーマットがデフォルトで発動するようになりました。
ただし、VS2015のソースコードエディターは、Update 3時点でもオートフォーマットのバグをいくつか抱えています。大半はVS2013時点では存在していなかったリグレッションです。VS2017は試していないので、不具合が修正されているかどうか、それとも依然として存在するかどうかは分かりません。なお、たとえMS Connectに不具合報告しても、VS2015では修正されず、どうせ新しいバージョンでしか修正されないことが分かり切っているので、報告するつもりはありません。また、せっかくユーザーが報告した不具合のチケットを、あろうことか勝手に削除することがあるようなので、MS Connectにはもう報告しないつもりです。傲岸不遜で恥知らずなMSにはもう協力したくありません。

フォーマット機能は、コーディング規約にそぐわないコードを整形するときは便利なのですが、意図しない形に勝手に自動整形されてしまうとイライラの原因になるだけです。また、明示的なフォーマットと、自動フォーマットとで整形結果が異なるときもあります。特にC#ラムダ式まわりで違いが具現化するのでイライラします。オートフォーマットが嫌いな人は、Visual Studioの設定で無効化しておくのが無難だと思います。

例1 (C++)

OpenGLDirect3Dで頂点バッファの初期データを定義するときによくある例です。

namespace
{
    struct MyVertex { float X, Y, Z; float Color[4]; };
    // 以下の行をカット&ペーストすると、Z の後ろのコンマと Color の間の空白がなくなる。
    const MyVertex Vertex1 = { 0.0f, +0.5f, 0.0f, { 1.0f, 0.0f, 0.0f, 1.0f } };
}

例2 (C++)

MFCが自動生成するコードとしてよく見られるものを、抽象化した例です。

class CMyDialog
{
public:
    CMyDialog() {} // 標準コンストラクター

// ダイアログ データ
    enum { IDD = 1 };
};

上記コードに対して明示的なフォーマットを実行したときに期待される動作は「// ダイアログ データの行が1レベルだけインデントされること」ですが、実際にフォーマットを実行しても何も起こりません。一方、カット&ペーストすると、// ダイアログ データ// 標準コンストラクターの開始桁位置と揃うように勝手にタブ文字および空白が挿入されてしまいます。

例3 (C++, C#)

void MyFunc()
{
    const int MyConst = 0; // 定数。
    // 処理。
    if (false) {}
}

上記コードに対して明示的なフォーマットを実行したときに期待される動作は「何も変更されないこと」ですが、C#の場合は、// 処理。// 定数。の開始桁位置と揃うように勝手にタブ文字および空白が挿入されてしまいます。また、C++においても、カット&ペーストするとC#同様に勝手な整形が実行されてしまいます。
行末尾のコメントを禁止するコーディング規約を採用している場合はこの問題に遭遇することはないと思いますが、勝手に桁位置を揃えられてしまうとイライラしますね。

例4 (C#)

class MyClass
{
    // ここで
    // #if false
    // #
    // と入力すると、既存の #region および #endregion のインデントが消失する。
    #region Fields
    int field;
    #endregion
}

通常、#regionおよび#endregionは対象となるコードブロックのインデントレベルに合わせてインデントされますが、このバグが発動するとインデントが消失します。

他にも、

    {
        ...
    }

というブロックを含むC++ソースファイルをフォーマットすると、なぜか

    {
        ...
}

というようにブロックのインデントが消失することもあります。このバグは発動条件が不明で、まったく同じソースなのに現象が出たり出なかったりと不安定です。確かVS2012か2013あたりまでは、少なくともこういった不安定な挙動を示すことはなかったように記憶しています。