«

""


[C++] Advent Calendarへの参加履歴 2010-2021

自分メモです

過去に参加した C++ Advent Calendar の自分の記事のリンク

C++ Advent Calendar jp 2010

Boost Advent Calendar 2011

C++ Advent Calendar jp 2012

C++ Advent Calendar 2013

C++ Advent Calendar 2021


意外と参加してました。。。

こうやって記録に残すのは、なんだか気分が良いですね


[C++] Modulesのコンパイル(MSVC ver)とBMIについて

この記事は C++ Advent Calendar 2021 1日目(初日!)の記事です。

少し前からC++に Modules がやってきました
C++20 対応のメジャーどころのコンパイラ(MSVC/gcc/Clang など)で使うことができます

個人的にはビックウェーブが来たーーーと思ってまして、つねづねポチポチと Modules について調べていました

それを少しまとめたいと思います

モジュールの説明

昔ながらのプリコンパイルヘッダの概念を、今風にした感じでしょうか

ヘッダファイルをインクルードしていたものを Modules に置き換えることが出来ます

ヘッダファイルだと、

インクルードの順番に気を付けたり
コンパイル時間が長くなったり
インクルードガード書いたりと
ゆーてローテク文字列だったのですが、

それがバイナリとして公式に提供されました

Modulesを記載するファイル

各コンパイラによって(推奨)拡張子が異なります

(参考)

以下、、MSVCで話を進めます
(コンパイラによって異なる所が多いので)

モジュールファイルについて

MSVC の場合、モジュールにしたいファイルは .ixx という拡張子を付けます
(Clangだと .cppm、GCCだと .cxx とかになります)

サンプルはこんな感じ

hello.ixx

1
2
3
4
5
6
// hello.ixx:
export module MyHello;

export int f() {
    return 42;
 }

利用する側はこんな感じで↓↓↓ import すれば使えます
(従来は #include "hello.h" とか書いていた場所です!)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// main.cpp 
#include <iostream>
#include <cstdlib>

import MyHello;  // モジュール使うよの宣言

int main() {
  auto a = f();

  std::cout << f();
}

サンプルだけ見ると、なんてことのないコードですね
メイン関数は #include してた箇所を inport に変更しただけです

モジュールをバイナリ化する

モジュールを記載する .ixx ファイルは、.ifc にプリコンパイルでバイナリ化されます

ややこしいのが、コンパイラによってこのあたりの呼び名が異なってて、こんな感じ

MSVC Clang
モジュールファイル名  → .ixx .cppm
モジュールファイルをプリコンパイルしたもの→ .ifc .pcm

ちなみに「モジュールファイルをプリコンパイルしたもの」を BMI と呼び、
Binary Module Interface の略になります

この BMI ファイルを各 cpp ファイルなどが import することになります

(参考)

VC++でのコンパイル方法

単純のため、まずはコマンドラインでやってみます

利用したVC++バージョンはこちら

コマンドは2つ

1
2
> cl /c /std:c++20 /EHsc hello.ixx
> cl /std:c++20 /EHsc /reference MyHello=MyHello.ifc main.cpp hello.obj

1つ目のコマンドでモジュールをプリコンパイルし、
2つ目のコマンドで obj をリンク、そして main.exe の出力をします

<1. モジュールのプリコンパイル>

C:\my\dev\sample_module01>cl /c /std:c++20 hello.ixx
Microsoft (R) C/C++ Optimizing Compiler Version 19.30.30705 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

hello.ixx

これで、hello.objMyHello.ifc が出来ました

(余談)cl.exe はモジュールのコンパイル時に同時に2つ(.obj.ifc)のファイルを出力してくれて楽です

Clang は別々のコマンドで出力するので、cl.exe とは少し作り方が異なっています
.pcm ( VC++で言うところの .ifc) を出力した後、それを元に .o ( VC++の .obj) を出力します
このあたりはまだ次回に投稿したいです

<2. 実行ファイル生成>

C:\my\dev\sample_module01>cl /std:c++20 /EHsc /reference MyHello=MyHello.ifc main.cpp hello.obj
Microsoft (R) C/C++ Optimizing Compiler Version 19.30.30705 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
Microsoft (R) Incremental Linker Version 14.30.30705.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj
hello.obj

main.exe が出来ました

実行してみます

C:\my\dev\sample_module01>main.exe
42

問題なし(^^♪

(備考)コンパイルオプションの注意点

VC++のコマンドラインオプションが

これらの間で一致していないとき、ワーニングが出ました(C5050

main.cpp(7): warning C5050: Possible incompatible environment while importing module ‘MyHello’: _CPPUNWIND is defined in current command line and not in module command line

そのため今回、hello.ixx 内では <iostream> は利用していないのですが、/EHsc オプションを付けています

(参考)

BMIってなによ?

プリコンパイルされた Binary Module Interface って何なのでしょうか?
この中身は一体?

さんざん調べましたが、大した情報が載ってないですね。。。

これ、BMIというのは Modules を扱うための概念のようです

これはコンパイルの過程のものなので、各コンパイラベンダーが作る箇所であり、明確に公開情報として詳細が提示されているわけではなさそうです
現時点では概念がちらほらと記載されているだけのようでした

実際に、プリコンパイルで作られた .ifc.pcm の中身は

がひとまとめにされてるようです

という記述を見つけましたが、出展元が判らなくなったので、思い出したら追記します。。。

(2021/12/4追記)
CppCon2019の資料が参考になりました!
Practical Cpp Modules - CppCon 2019
https://github.com/CppCon/CppCon2019/blob/master/Presentations/practical_cpp_modules/practical_cpp_modulesboris_kolpackovcppcon_2019.pdf

もちろん、コンパイラによって、さらにバージョンによっても形式は様々なんでしょう

モジュールの配布ってどうやるの?

モジュールのバイナリを配布することはできないです
共有する場合はあくまでソースコードと共に配布になります

また、作られた BMI、つまり .ifc.pcm ファイルは不変的なバイナリではないみたいです

ライブラリのように配布はできないのですね。。。

(余談)Modules の提案を推し進めている Gabriel Dos Reisさん は、Common Module Interface Format を作りたいみたいですが…
具体的に今の段階では、配布目的のものは出ていないようです

(参考)

所感

まだ2021年12月の時点では、Modules 機能が完全に動作するコンパイラもないみたいですし
そもそも各コンパイラによって記載方法や推奨が異なるので、なんとも道半ばな印象はあります

Modules を利用するための手順やお作法も多く、また情報も限られているので、取り組みにくいですね

マイクロソフトの VC++チームブログ は、コンパイラベンダーとして結構 Moduleds の具体的な情報を出しているように感じました
(Clangももうちょっと頑張って。。。あとGCC。。。おまえはやる気あるのか。。。)

Modules に関して取り組まれている人たちの歴史はとても長く
かつ現在のヘッダファイルがベストだとは思えないので
個人的に一押ししたい機能だと改めて思いました

所感その2

C++ Advent Calendar!

ずいぶん昔に一度だけ参加したことがあったのですが、それからなーんにもしてませんでした

今回、意を決して投稿できて良かったです

かなりよく調べたつもりですけど、間違いなどあったら気軽に @hr_sao まで教えていただけると嬉しいです

C++楽しい~♪


[C++] 実行環境の差異によるintワーニングが出ない書き方

C++のワーニングを放置していたのですが、そっと @srz_zumix さんが教えてくれてました

忘れないうちに”φ(・ェ・o)~メモメモ


x86環境とx64環境が混在してる場合にエラーが出やすい

こんなやつとか出ます…

1
2
3
4
5
6
// Warning が出る例
std::vector<int> my_vec = { 0, 42 };
uint32_t max_loop_counter = my_vec.size();  // ←ここね
uint32_t counter = 0;

// 以下、counter を max_loop_counter までなんらかの処理

これは x86環境だと warning は出ないのですが x64 環境想定でコンパイルすると、ワーニングが出ます

(Clangの例)
warning: Implicit conversion loses integer precision: ‘std::__1::vector >::size_type’ (aka ‘unsigned long’) to ‘u_int32_t’ (aka ‘unsigned int’) [-Wshorten-64-to-32]

( ̄□ ̄;
ええ、ええ、判っていますとも…
int 型が処理系によって異なるのは…

そこで、やっつけで修正するならこれ

1
2
// ベタにワーニングを取ろうとするとこんな感じ
uint32_t max_loop_counter = static_cast<uint32_t>(my_vec.size());

なのですが、もっとスマートは方法があります

1
2
3
4
// 今っぽい感じに
std::vector<int> my_vec = { 0, 42 };
auto max_loop_counter = my_vec.size();
decltype(max_loop_counter) counter = 0;

エレガントになりました…!素晴らしい(^^♪

警告のコンパイラー対応表がある

@srz_zumix さんが最近始められたプロジェクトらしいです

ワーニング対応表欲しいな…と思っていたところなので、結構良いかもしれない…

そして今日もC++修練は続く…


[c++] 2次元配列的な書き方

自分メモ

2次元配列

C++11 以前では、2次元配列はこんな感じで書いていました

1
2
3
4
5
6
// 2-dimensional array (raw type)
constexpr static float xy_raw[][2] = {
      { 0.f,  10.f}  // 0
    , { 20.f, 30.f}  // 1
    , { 40.f, 50.f}  // 2
};

これでも悪くは無いのですが、生配列を扱うと範囲外アクセスに気が付かない可能性が出てきます そこで C++11 から境界チェックが出来る配列の std::array が登場しました
これを使えば、C-styleの配列のノリで扱うことが可能です

さらに2次元配列にしたければ std::arraystd::vector に入れることで実現可能です

1
2
3
4
5
6
// 2-dimensional array (using stl)
const std::vector<std::array<float, 2>> xy_array = {
      { 0.f,  10.f}  // 0
    , { 20.f, 30.f}  // 1
    , { 40.f, 50.f}  // 2
};

悪くなさそう

動作確認

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <vector>
#include <array>

int main() {
  // ---------------------------------
  // 2-dimensional array (raw type)
  constexpr static float xy_raw[][2] = {
        { 0.f,  10.f}  // 0
      , { 20.f, 30.f}  // 1
      , { 40.f, 50.f}  // 2
  };

  std::cout << "xy_raw[0][1]: " << xy_raw[0][1] <<  "\n"; // 10

  // xy_raw[1][2] は out of rangeだけど warningになってる
  // これはたまたま xy_raw[2][0] と同じなので動作しているだけ
  std::cout << "xy_raw[1][2]: " << xy_raw[1][2] <<  "\n"; // 40

  // ---------------------------------
  // 2-dimensional array (using stl)
  const std::vector<std::array<float, 2>> xy_array = {
        { 0.f,  10.f}  // 0
      , { 20.f, 30.f}  // 1
      , { 40.f, 50.f}  // 2
  };

  std::cout << "xy_array[2][0]: " << xy_array.at(2).at(0) <<  "\n";  //40  

  // compile error
  //std::cout << "xy_array[1][2]: " << xy_array.at(1).at(2) <<  "\n";  // out of range accsess
}

結果

xy_raw[0][1]: 10
xy_raw[1][2]: 40
xy_array[2][0]: 40

コンパイル時に教えてくれるので助かります

参考


[C++] std::optionalの使い方を紹介しました

少し前ですが、std::optional について nakameguro_feature.cpp vol.13 で発表したので、その資料を置いときます

私的感想としては、optional を使うと
値取得に失敗しても、例外を書くことなく if で処理出来る のが、なんだか良いなぁと思った次第でした

あと、optional の無効状態をどう表すか?
reset() / std::nullopt / {} のどれよ?
という話は、参加者の人たちの意見も GitHub の検索結果と同じで
reset() に軍配があがっていました(‘ω’)

こういう意見交換の場は、本当に恵まれてるなぁ~しみじみ

次回は 3 / 28 (木)開催で、vol.18 です!

お時間ある方は、ぜひお立ち寄りください~!


[Android] 謎のエラー「Unable to start debugging.」が出たときの対応

Androidデバッグで実行時エラー

環境

ある時…Visual Studio で作っている Android プロジェクトが、実行時エラーになりました

Unable to start debugging. Check your debugger settings by opening project properties and navigating to ‘Configuration Properties–> Debugging’

デバック出来ないからね!プロジェクトの設定見てね!的な意味みたいですが
デバッグモードで動かしてるし…
一体どこの何の事を言ってるのか判らない…><。

リリースモードならOKなのかしら?と思っても、同様のエラー”(-“”-)”

解決案(わたしはこれでは解決しませんでしたが)

検索しても、実のある回答は特に出てこず…
唯一、解決っぽいのが、NVIDIAさんのフォーラムに載ってました

元ネタリンクはMicrosoftさんのGitHub情報みたいです

簡単に言うと、VSの Developer Command Prompt を使って、キャッシュクリアしてみたら?というもの
やってみました

  1. Developer Command Prompt を検索して立ち上げる

  2. 以下のコマンドを打つ

Devenv /UpdateConfiguration
Devenv /ClearCache

もっともらしい対策なんですけど、わたしの実行時エラーは解決しませんでした
何がダメなのだろ…((+_+))

わたしが解決した方法

で、実際の解決策ですが…
すみません、散々あーだこーだ書いてますが
スタートアッププロジェクトの設定もれ でした…( ;∀;)
いやはや、お恥ずかしい…

Androidプロジェクトが参照する、別のプロジェクト達が
同じソリューションファイルの中に複数存在しています

なのに、Androidプロジェクトを起動プロジェクトに設定しておらず…

ポカミスとはまさにこの事!( ;∀;)

なぜこれに気が付かなかったのか…相当焦ってて、周りが見えてなかったみたいです

二度と同じ過ちを繰り返さないように…><。
あと、同様のエラーで困ってる人の何かしらの参考になればと思います><。


[C++] VisualStusio2015でClangを使う設定

今日は Clang with Microsoft CodeGen の設定などについて、メモしておきます

先人たちが既に色々と試している内容と対して変わりませんが、そもそも日本語の情報も少ないので、何かの足しになればと思います

“Clang with Microsoft CodeGen” is here!

最近はすっかり、クロスプラットフォームやオープンソースに力を入れているマイクロソフト社のツールセットの中に、Clang対応ってのがあります

2015年の年末にですが、Clang が正式に Visual Studio 2015 Update1 で利用できるよ~
とVC++チームブログで発表されていました

良いですねー(^^)
現在のVS2015には Clang with Microsoft CodeGen というツールセットが提供されており、目玉はなんといっても、Clang のデバックを Visual Studioのエディターで確認できるところでしょうか!

他にも、Clang でコンパイルしたobjと VC でコンパイルしたobjがリンクできるところもすごいです
既存資産をフル活用出来そうですね

(2016/5/15現在、Visual Studio 2015 Update2 が最新です)
https://www.visualstudio.com/ja-jp/news/vs2015-update2-vs.aspx


LLVM側にも記事が上がっています


日本でも既に先人が試されているので、読んでみると良いと思います


ちなみに、この Clang with Microsoft CodeGen は VC++チームブログにも “a.k.a. Clang/C2” と記載されており、別名を Clang/C2 というようです

また、今回対応している Clang 側のバージョンは 3.7 です

clang.exe の場所

Clang

1
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\Clang 3.7\bin\x86\clang.exe

ちなみにVC++

1
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\cl.exe

どちらでも、コマンドプロンプトでコンパイル可能です

VSでのコンパイラの切り替え設定

Visual Stidon 2015 上で “Alt + F7” を押すか

プロジェクト > [プロジェクト名]のプロパティ

で設定UIを表示させます

構成プロパティ > 全般 > プラットフォームツールセット

この項目を “Clang 3.7 with Microsoft CodeGen (v140_clang_3_7)” に変更するだけです

結構簡単\(^o^)/

ソリューション作成は何でもOK

上記の様に、コンパイラが簡単に切り替えられるので、空のプロジェクトでも、Win32コンソールアプリケーションでもOKです

一応、Clangっぽいプロジェクトはあるんですけど、いきなり dll というのもなんだか敷居が高いので、

exe を作りたいだけなら、Win32コンソールアプリケーションで良いと思います

[余談]文字コードはUTF8の方が良い(様な気がする)

最初に書いておくと、Sift-JIS でも Clang/C2 でコンパイルは通ります

…なのですが、一応、なんとなく

個々の環境によって異なるのかもしれませんが
わたしがVS2015で作成した cpp ファイルは、デフォルトで Sift-JIS になります

既に、VC++チームブログ にはこんな感じで↓↓↓

If source files in the project you are trying to convert are UTF-16 encoded, you will need to resave them as UTF-8 when Clang gives you an error about UTF-16 encoded source with BOM.

UTF-16はだめらしいです
Sift-JIS は無関係かもしれませんが、一応…

サンプルコード

cpprefjp を参照して、サンプルコードを書いてみました

VC2015 Update2 では未対応だけど、Clang 3.7 は対応しているというコードです

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include "stdafx.h"
#include <iostream>

constexpr int f()
{
	int result = 0;
	return result;
}

int main()
{
	std::cout << "Hello: " << f() << std::endl;

	return 0;
}

Visual Studio 2015 (v140) でコンパイルすると、エラー

VS2015 ではまだ、constexpr関数内の変数宣言がエラーになる様です

Clang 3.7 with Microsoft CodeGen (v140_clang_3_7) でのコンパイル

Clang はOKです
いい感じに動作しました!


VC++も Clang も、VS上でデバック出来るのは良いですね
噂には聞いていましたが、自分で動作させてみると、感激するもんがあります

今はまだプレビューらしいので、早く安定化して欲しいですね~


[勉強会] ebisu_effective_modern.cpp vol.3やりますよ

ebisu_effective_modern.cppって?

東京の恵比寿でC++について、みんなの意見を聞きながら本を読み進める勉強会を開いています

昔、大阪でC++の読書会を開催していたのですが、それが結構役に立って面白かったので、東京でも開催してみよう!と思い、始めてみました

ネタが無いと勉強や会話もしずらいので、
「Effective Modern C ーC11/14プログラムを進化させる42項目」 を元に進めています

今回は、5章 右辺値参照、ムーブセマンティックス、完全転送 について…
前回の vol.2 では、基本的なムーブの動きを簡単に抑えた程度になったので、あまり深いところまでは進めませんでした
書籍の内容にぐいぐい追いつけるように頑張りますよ~

興味ある方はどうぞ、お気軽にお越しください(^^)/


[C++11] 参考リンク情報

C++11について調べているときに参考になった情報源のメモ

VS2013とVS2015 previewで利用できる機能一覧が乗っている


[C++/CX] MVP Community Camp 2014大阪で「VC++まわりの非同期処理」セッションしました

MVP Community Camp 2014大阪にて、VC++系のセッションをさせて頂きました

MVP Community Camp 2014大阪会場
http://atnd.org/event/E0024087 (リンク先は削除されている模様です)

当日利用した資料はこちら!


 pptx版はこちら  ←セッション時の私的メモが欄外に載っています
 PDF版はこちら

序盤はわたしの追体験発表みたいになってしまいました
同じような疑問を持っている人や、その人なりの解釈の手助けになる様であればと思って記載しています

後半部分は、VC++での非同期処理の触りだけになっていますが
非同期での例外や中断など、C++/CXのWIndowsストアアプリでは興味深い仕組みが色々あるので
この続きになる情報も、もっと自分なりに勉強して発信していきたいなー