vcpkgでinstallするとCould not locate a complete toolsetとか言われる。
概要
Warning: The following VS instances are excluded because the English language pack is unavailable. C:\Program Files (x86)\Microsoft Visual Studio\2017\Community Please install the English language pack. Could not locate a complete toolset.
解決策
素直に書いてある通りに新しくインストーラーを持ってきて英語の言語パックを入れましょう。
ビルドチェーンが言語パックに依存しているの何とかならないんですかね。500MBくらいあるし。
その他
最近流行りのgrpcとかも難なくビルドできるし、思ったよりも良さげになってきましたね。vcpkg
googleのprotobufとかもウィンドウズならvcpkg使えよって感じになってきているし期待しても良いかもしれません。
少なくともgypよりはるかにビルド簡単なので素敵です。
自分のプロジェクトを組み込むのはまだ難しそうですが。
C++17から導入される範囲 for ループの制限緩和で何が変わるか
概要
C++17で範囲forループのbeginとendで違う型を指定できるようになりました。
範囲 for ループの制限緩和 - cpprefjp C++日本語リファレンス
これによって何が変わるのでしょうか。
イテレータの思想の違い
STLのイテレータはメモリはコンテナが持ってイテレータは最小限の値のみ持つという思想で作られていました。
一方マイクロソフトの提供するAPIはイテレータ自体が終端の判断をする機能を持つことが多いです。
その思想の違いをこの制限緩和は扱いやすくしてくれます。
親プロセスの名前を取得するサンプル
#include <iostream> #include <optional> #include <Windows.h> #include <TlHelp32.h> struct SelfOperationTag {}; class ProcessEntryIterator { public: ProcessEntryIterator() { processEntries = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (processEntries == INVALID_HANDLE_VALUE) { result = false; return; } processEntry.dwSize = sizeof(PROCESSENTRY32); result = Process32First(processEntries, &processEntry); } ~ProcessEntryIterator() { CloseHandle(processEntries); } const PROCESSENTRY32& operator*() { return processEntry; } void operator++() { result = Process32Next(processEntries, &processEntry); } operator bool() const { return result; } private: HANDLE processEntries; PROCESSENTRY32 processEntry; bool result; }; bool operator!=(const ProcessEntryIterator& iterator, SelfOperationTag) { return iterator; } class Toolhelp32Snapshot { public: auto begin() const { return ProcessEntryIterator(); } auto end() const { return SelfOperationTag(); }; static std::optional<PROCESSENTRY32> Find(DWORD processID) { for (const auto& processEntry : Toolhelp32Snapshot()) { if (processEntry.th32ProcessID == processID) { return processEntry; } } return std::nullopt; } }; int main() { auto currentProcessID = GetCurrentProcessId(); auto currentProcess = Toolhelp32Snapshot::Find(currentProcessID); if (currentProcess) { auto parentProcess = Toolhelp32Snapshot::Find(currentProcess->th32ParentProcessID); if (parentProcess) { std::wcout << parentProcess->szExeFile << std::endl; } } }
煩雑なエラーハンドリングで抜けが出てしまいにくいのではないでしょうか。下記サイトでは現実的には起こらないでしょうがProcess32Firstのエラーハンドリングが抜けています。
モジュールの列挙 (PSAPI)
正しくハンドリングしてgotoやdo whileが出てくるのも辛いものです。
Windows-classic-samples/shared.c at master · Microsoft/Windows-classic-samples · GitHub
Visual Studio2017にVsVimをインストールすると上スクロールがバグる
概要
新しい環境にVisual Studio2017とVsVimをインストールすると上スクロールの際に期待しない動きをすることがある(2/3回)
バグの再現させ方
文字の折り返しが起こっているスクロールできるファイルでGHと移動すると私の環境では画面一番上の行にカレント行が移動し、カレント行が表示画面の一番下に行く。
暫定的な対処
.vimrcに下記を追加。
nnoremap H Hzt
C++17からはwstring_convertが非推奨となるので環境毎のコードが推奨される
概要
推奨されるマルチバイト文字変換。
非推奨
C++17からスタンダードライブラリのものは非推奨になる
Visual Studioで下記のようなコードをC++17を有効にした状態で書くと
#include <codecvt> #include <locale> int main() { std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter; }
エラー C4996 'std::codecvt_utf8<wchar_t,1114111,0>': warning STL4017: std::wbuffer_convert, std::wstring_convert, and the
上記のようなエラーが出る。
推奨
それをふまえて、windows環境で推奨されるマルチバイト変換は下記のようになるだろう。
std::basic_string::dataメソッドの知名度が低い。
C++の難しめな用語集
概要
先日、言いたい用語がすぐに出てこなかったので備忘録を作った。私が学習するのが遅かったり難しかったものを集めた。
その特性から多くは語らないのでググって。
Return Value Optimization (RVO)
- Named Return Value Optimization(NRVO)
データ指向設計 (Data Oriented Design)
- キャッシュライン
Perfect Forwarding
引数と全く同じ型を伝搬させるという説明が一番分かりやすかった。
universal reference
- Rvalue
- Lvalue
Template MetaProgramming(TMP)
メインの機能はconceptに代替されそう。
- Substitution Failure Is Not An Error(SFINAE)
Type Erasure
Argument Dependent Lookup(ADL)
安易にusing namespaceしてると引っかかるやつ。
unqualified name look up
Unqualified name lookup - cppreference.com
One Definition Rule(ODR)
- ODR違反
- odr-use
- リンケージ
Application Binary Interface(ABI)
C++ではないが。
Most vexing parse
レイアウト
- Plain Old Data(POD) C++20からtrivial classとして扱う
- standard-layout class
- trivial class
Rust
Rustも同じレベルのプログラミングができるので、Rustの概念を用いてC++の概念を説明しても良いはず。
- LifeTime
- Ownership
規格
- Working Draft
- well-formed
- undefined behavior
C++er は“合法”だとか“違法”だとか言いたくて仕方がないけれど、結局どういう意味? それより適合・適格・○○動作・○○規則・診断不要いろいろの関係が謎
ガイドライン
- Guideline Support Library (GSL)
VisualStudio2017はC++17に対応しているがデフォルトでは無効になっている
C++17を有効にする
プロジェクト > プロパティ > 構成プロパティ > C/C++ > 言語 > C++言語標準
から設定できます。
せっかくMSが標準まで追いついてくれたのに有効にしないともったいないです。
おまけ
上記を言いたかっただけなんですが、あまりに短かったのでVisualStudioで私が使う設定を書いておきます。
ツールバーにあるソリューション構成ドロップダウンリストの幅変更
デフォルト幅だとUnreal Engineのビルドをするとき等にソリューション構成名が長すぎて今何ビルドしているか分からなくなるので設定してます。
用語が限定的過ぎてググラビリティがやたら低くて毎度見つけるのに苦労します。
後、さっき調べて知ったんですがテキストが編集可なのがコンボボックスで編集不可なものがドロップダウンリストらしいです。
同じものを指す用語かと思ってました。
ClangFormat
コーディングスタイルを設定できます。
Visual Studioデフォルトのフォーマットが気に入らないなら変更しましょう。
独自のコーディングスタイルを選択するよりはデフォルトフォーマットを選択した方が良いとは思いますが。
ツール > オプション > テキストエディター > C/C++ > 書式設定 > 規定の書式スタイル
メンバ変数の色変更
Visual Studioのハイライトは優秀で言語内部の概念に対しても色を変えることができます。
しかしビルドに依存するのでUEぐらいの複雑なプロジェクトになるとハイスペックPCでも1分くらいハイライトが消えることがあります。
メンバ変数はコード上だと全くの宣言なしでいきなり登場するので視認性を上げると心が落ち着きます。
ツール > オプション > 環境 > フォントおよび色 > 表示項目 > C++フィールド
Chromeとかで使われているグラフィクスライブラリSkiaのWindowsビルド
手順
git clone https://github.com/google/skia
masterブランチだとWindowsに優しいものが入っていないのでtagを使います。
git checkout -b dev refs/tags/chrome/m39_2138
上記タグのコミットだとリポジトリルートにmake.batが存在するので、こちらをVisual Studioの環境変数を適用した上で実行するとビルドできます。
環境変数の準備は一般的に面倒なので設定済み開発用コマンドプロンプトを利用すべきでしょう。
VSのインストールパスの下記バッチファイルを起動させたり、ウィンドウズアイコンのインストールしたアプリから呼ぶこともできます。
VisualStudio/Common7/Tools/VsDevCmd.bat
ただ1つだけ罠があって、いくつかのファイルがBOMなしutf-8で保存されているためビルドが失敗します。
私はそれらのファイルにBOMを追加することで対応しました。
最初はファイルエンコードを一致させることで解決しようと思ったのですが他のファイルにvimで:set fenc?としても
fileencoding=としか返してくれず諦めました。読み取れなかったらこうなるんですかね。
参考
この記事によりBOMなしutf-8が原因だと気付けました。ありがとうございます。