旧版の2023Aではエラー吐きます 以下からローカルに落とす必要があります
コンパイルする.texファイルと同じ場所に置いとけばパスが優先されます
原因?
もしかしたらexpl3.styの最新の仕様とミスマッチしている可能性がある
変数宣言あたりで何か改訂があったかもしれない
昨年7月までは普通に動いていたので…
IEEEtran.clsを使ってConferenceを投稿したので備忘録
ieee.orgの配布ページ,https://www.ieee.org/conferences/publishing/templates.html
LaTeX TemplateとBibteX Templateがあるので両方を入手する
もしくはTeXLiveのieeetran
に双方が入ってるはずのでそれを使う
いずれにせよ日本語に非対応,pdfLaTeXでコンパイルする,vscodeのlatexmkのデフォルトコマンドで動くかも
IEEEtran.cls
IEEEabrv.bib
IEEEfull.bib
だと全ての固有名詞が省略形ではなくなるらしいIEEEtranN.bst
plainnat
スタイルが使えるIEEEtran.bst
を使うnatbib
plainnat
を扱えるエンジンIEEEtranN.bst
を読み込むpaper.tex
confs.sty
biblio.bib
\documentclass[conference]{IEEEtran} \IEEEoverridecommandlockouts \usepackage{confs} %confs.styで設定を管理する \begin{document} \title{ %タイトル \thanks{} %カネの話をする } \author{ \IEEEauthorblockN{} %名前 \IEEEauthorblockA{ \textit{} \\%分野 \textit{} \\%所属 \\%都市,国家 %連絡先メアド } \and \IEEEauthorblockN{} %名前 \IEEEauthorblockA{ \textit{} \\%分野 \textit{} \\%所属 \\%都市,国家 %連絡先メアド } } \maketitle \begin{abstract} %概要 \end{abstract} \begin{IEEEkeywords} %キーワード \end{IEEEkeywords} \section{} %本文 \appendicies %複数の附録に対応 \renewcommand{\theequation}{\thesection.\arabic{equation}} %数式番号を再定義 \numberwithin{equation}{section} %数式番号の表示を再定義 \section{} %附録 \section*{Acknowledgment} %謝辞 \bibliographystyle{IEEEtranN} %文献リストのスタイルを召喚 \bibliography{IEEEabrv,biblio} %biblio.bibの文献リストをIEEEabrv.bibの補完を適用して召喚 \end{document}
\usepackage{textcomp} % 特殊文字シンボルを追加 \usepackage[numbers,sort&compress]{natbib} %IEEE仕様でnatbibを召喚 \renewcommand{\bibfont}{\fontsize{8pt}{10pt}\selectfont} %文献リストのフォントサイズを定義 \setlength{\bibsep}{0pt} %文献リストの間隔を圧縮 \makeatletter \renewcommand{\@biblabel}[1]{[#1]\hfill} %文献リストの表示を定義 \makeatother \usepackage{float} %図表の配置 \usepackage{here} %図表の強制配置(非推奨) \usepackage{tabularray} %表ライブラリ \SetTblrInner{rowsep=4pt,colsep=4pt} %tblr環境を見やすくする \usepackage{stackengine} %いろんな場所で無理矢理に改行つきレイアウトを入れる \usepackage{amsmath,amssymb,amsfonts,mathtools} %数学ライブラリ \usepackage{autobreak} %数式の自動改行 \usepackage{empheq} %並列した数式を立てる \usepackage{mleftright} %括弧等のスペースを詰める \usepackage{bm} %ベクトル表現に使う \usepackage{siunitx} %単位表現に使う \usepackage{wrapfig} %周り込みで図を入れる \usepackage{caption,subcaption} %図に2層のキャプションを入れる \captionsetup{labelsep=period} %Fig.N:ExplainではなくFig.N.Explainみたいにする \usepackage{graphicx} %図ツール \usepackage{xcolor} %色操作ツール
natbib
を使う理由推奨されているIEEEtran.cls
とcite
とIEEEtran.bst
のコンビでは,一箇所に複数の文献を配置するとそのレイアウトが圧縮されない,cite
の仕様としては圧縮されるべきところIEEEtran.cls
と一緒に使うと圧縮禁止オプションもなしに強制的にそうなってしまう,なぜならそれがIEEEのスタンダードスタイルらしいので
要するに[1][2][3][5]を[1-3,5]としたい時はcite
ではなくnatbib
とIEEEtranN.bst
を使いながら文献リストのスタイルを自力で修正する必要がある
appendices
の数式番号({セクション番号}.{メイン数式番号}({サブ数式番号}))
の形式を取る,A.1とかA.2aとかそんな感じになる
結論から言うと,バトル終了後の3倍目押し広告は,macOSでやるなら絶対に押すな
なお普通の広告でもたまにバグるので,Apple Siliconではそれを覚悟してプレイしろ
もしくはスキップ券を買え(完全なる対処法は実質的にそれしかないと考えられる)
Mintegralは広告でユーザにゲームの簡易版をプレイさせるSDK
30秒広告(報酬広告)でゲーム関係の場合に5割程で出てくる
パズルゲー(例えばRoyal Matchの一部)が該当するカスがよ
単純にアフィのリンクが出るタイプでは使われないので運ゲー
進行不能であるため強制終了が必須(⌘+Qでは終了できない)
なぜかバトル終了後の広告に出現率が偏っている気がするが…
ちなみにスマホアプリであれば問題ない,理由はわからない…
広告画面を閉じた後でブラウザを開かせるタイプの広告に注意
何も表示されないウィンドウが出現した際に完了を押すと発生
進行不能であるため強制終了が必須(⌘+Qでは終了できない)
ちなみにスマホアプリであれば問題ない,理由はわからない…
バトル終了後に広告を再生してからリザルトに遷移する時点でフリーズする
アプリそのものがハングするため強制終了が必須(⌘+Qでは終了できない)
そもそも任意の広告のロード時にフリースする可能性が否定できないという
アプリそのものがハングするため強制終了が必須(⌘+Qでは終了できない)
ドロップされたブースターを開封する時点から操作不能となる
進行不能であるため強制終了が必須(⌘+Qでは終了できない)
枚数更新は反映されたりされなかったりするが原因条件は不明
1面タイマンでは堤防を規定値で破壊してから根城を破壊する
爆撃スキルで堤防と根城を同時に破壊するとクリア不能になる
なぜか堤防も根城も消滅しないがフラグ管理がおかしいのでは
とりあえずはホームボタンで仕切り直すことで脱出ならできる
2面タイマンでは2つの根城を両方とも破壊する(1 vs 1 vs 1)
だが同時に破壊すると根城が消滅しボーナス稼働が不発する
どうしようもないので観念してリザルト画面を待つしかない
もしくは順番に各個に破壊する技術を身につける必要がある
小型根城と大型根城があるコースで小型根城を破壊せず大型根城を破壊するとクリア不能になる
自分と相手のDPS差が大きい時に本丸を先に破壊する,または爆撃スキルで本丸を先に破壊する
通常コースの2週目もしくはBOSSコースで起こる,順番に破壊する技術を身につける必要がある
とりあえずはホームボタンで仕切り直すことで脱出ならできる,フラグ管理がおかいしいのでは
Apple ID等でアカウントを作成しても,カード枚数は端末ごとに保存されており,全体で同期されることはない
ログインの際にカードレベルとコイン枚数のデータがサーバから端末上へと同期される
しかしサーバ上のカードレベルとコイン枚数のデータは端末から一方的に上書きされる
つまり複数の端末で同時にログインして種類が被らないようそれぞれからカードレベルを上げる処理をすればコイン枚数の消費量を減らせる(規約的にギリギリかもしれない?)
アプデで対策されたらしく草 クリア時の通信が強制的に遮断されるようになりMac周回の旨みが死んだ ただ現状ではまだ高級ルーレットが回せる強みがあるので物事は考えよう
アクセス指定子をつけると設定できる
private
該当する関数または変数には,それらが実装されたクラス(のメソッド)のみアクセスできる
protected
該当する関数または変数には,それらが実装されたクラス(のメソッド)とそのクラスから派生したクラス(のメソッド)のみアクセスできる
public
制限はない,オブジェクトを無から生成して渡すためにpublic
の関数を経由する必要がある
継承時にアクセス指定子をつけると継承元の関数または変数のアクセス権限にリミットがかかる 隠蔽する方向にのみ動作する
private
public
とprotected
がprivate
になる
class A{ private: int x; // can't acccess from B protected: int y; public: int z; } class B:private A{ // y -> private // z -> private }
protected
public
がprotected
になる
class A{ private: int x; // can't acccess from B protected: int y; public: int z; } class B:protected A{ // y -> protected // z -> protected }
public
制限はない
class A{ private: int x; // can't acccess from B protected: int y; public: int z; } class B:private A{ // y -> protected // z -> public }
using
と::
でスコープをつけながらエイリアスを作成する際,アクセス指定子を先頭につければ個別に上書きできる
protected
からpublic
にする
class A{ protected: int x; } class B:public A{ public using A::x; // reachable A.x from public, protected, private }
特に思いつかないし,こんなものが必要になるような場面に遭遇したら,ひとまず設計を修正した方が良い気がしています
これがどうやら存在しないらしい.やるならば全てに一対一でpublic using Class::name
を叩く必要があるらしい
public
からprotected
にする
class A{ public: int x; } class B:public A{ protected using A::x; // reachable A.x from protected, private }
public
からprivate
にする
class A{ public: int x; } class B:public A{ private using A::x; // reachable A.x from private }
protected
からprivate
にする
class A{ protected: int x; } class B:public A{ private using A::x; // reachable A.x from private }
部分的にprotected
をprivate
にしたいです,特に組込実装ではコード領域すらも節約する必要があるかと思います
つまり継承時にアクセス権限の規制をやれということで
名前衝突や菱形問題の原因になるのでやめたい もしくはせめて仮想継承をちゃんと実装したい
衝突しなかったらスコープ無しで派生クラスから呼べる 衝突したらスコープ派生元クラスを解決する必要がある もし衝突してもエイリアスの作成は1個までならセーフ
class A{protected:int x;}; class B{protected:int x;}; class C:public A, public B{ public: using A::x; // -> OK // public: using B::x; -> error }; int main(void){ C c; c.x = 0; }
言い換えれば権限の変更は1個しかできないということ むしろ今までのケースが「衝突しなかったらスコープ無しで派生クラスから呼べる」のを悪用して同名の再定義をしている
これらの例はA
とB
にそれぞれ独立にx
があった上でC
に合体させたせいで詰んでいるが,x
を持つA
からB
とC
に派生させた上でD
に合体させるような場合,(B
とC
が悪さをしない限り)仮想継承でx
は何とかなるかも
#include <iostream> using namespace std; class A{ protected: int x; }; class B: virtual public A{}; class C: virtual public A{}; class D: public B, public C{ private: using C::x; protected: using B::x; public: using A::x; // both lines are equivalent in operation (why?) // `public` is needed to be specified in the end }; int main(void){ D d; d.x = 1; //d.A::x = 1; -> error if A::x is placed in protected cout << d.x << endl; };
A::x
の実体をB::x
もC::x
もD::x
も指すが,アクセス権限はA::x
とB::x
とC::x
とD::x
でそれぞれ設定され,かつusing
でエイリアスを作成するとその都度に設定が上書きされる(これでも実体は1つなので問題ない)
最終的にD
でpublic: using
するとD.x
を介して実体を操作できる
これをコピペして連打すればOK
var elementClass; var elementClassArray; var button; elementClass = document.getElementsByClassName("deleteIcon"); elementClassArray = Array.from(elementClass); elementClassArray.forEach((element,index)=>{ element.click(); button = document.getElementsByClassName("formBt01 submitButton"); button[0].click(); }); window.location.reload();
reload();
自動化やるのはダルい
first aidするべきは該当のコンテナではなく1つ上のレイヤのコンテナである
例えばHDDの物理イメージがdisk4
だとしたら,その下にコンテナとしてdisk4sX
がいくつかあり,パーティションとして仮想イメージのdisk5
やdisk6
がそれらを指している
おそらく問題が起こるのはその下のdisk5s1
やdisk6s1
だが,こいつにfirst aidしても上記のメッセージが出て解決しない,チェックサムが壊れたのかその仕様が変更されたのか…
そこでdisk5
やdisk6
にfirst aidするとdisk5s1
やdisk6s1
が破損していると認識して修復しようとしてくれる,あとは復活するのをお祈りする,そこそこ時間がかかるので注意
macOSの下の方で走っているOSのこと
最後に完全に公開されたのはmacOS 10.13.3の時で,以降はPure Darwinにフォークされて断絶しているっぽい
github.com
Wikipediaでもこの程度
en.wikipedia.org
強いて言えば最新版は22.3.0だということが確実にわかってるくらいか?
Darwinの下の方で走っているkernelのこと
macOSの下のDarwinの下のルートにいる
こっちは今も更新されてる可能性がある
github.com
X is not UNIXという意味らしい,はえ〜
terminalで
uname -a
みんなの結果を教えてね!
俺のMacbook Proから持ってきた
Darwin 22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:38:37 PST 2023; root:xnu-8792.81.3~2/RELEASE_ARM64_T6000 arm64
Bingでヤケクソで「"release_arm64" "M2" macbook pro」で検索したらこんなものが見つかった
Darwin 22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:39:46 PST 2023; root:xnu-8792.81.3~2/RELEASE_ARM64_T6020 arm64
こないだ出たM2 Macbook Proか github.com ちなみにGoogleではこのページがヒットしなかった,冗談抜きにBingの方が検索能力が高いかも…
最近のヤツなら
RELEASE_X86_64
だが,昔のやつだと
RELEASE_I386
というのもあったらしい
それより前はわかんない
「"Darwin" "RELEASE_ARM64"」やら「"Darwin" "RELEASE_X86_64"」やら「"Darwin" "RELEASE_I386"」で検索するとけっこう出てくる
多分ここにほとんど網羅されている? www.theiphonewiki.com
MacBook Pro (15-inch, 2016)がもうすぐ発売から7年が経過して諸々(OSや修理など)のサポートが切れるので,2023年3月にMacBook Pro (16-inch, 2021)の認定整備済品を買った.
2023年1月にM2シリーズのモデルの発売が開始したが,その余波でM1シリーズのモデルの価格に値下げラッシュが始まった.
また2022年後半には円安が進行し,クソ政府のせいで将来的な円高要因や対物価比の賃金上昇兆候がほぼ見出せない.
M2はM1に対してスペックはマイナーアップデート程度であり,比で考えても値上がり幅が酷すぎるせいでコスパが良くない.
2021年発売モデルが中古化して認定整備済品が値下げした今,Intel系MacからApple Silicon系Macに乗り換えるべきである.
さらに,Venturaも最初はバグまみれだったが,そろそろメーカーもM1かつVenturaに対応するリリースを出す頃合いだろう.
ちなみに,MacBook Pro (15-inch, 2016)はまだビンテージ品の扱いなので,やろうと思えばまだ修理は可能…かもしれない
ぶっちゃけ,またキーボードが壊れたし,OSやAppが高機能化しているせいでファンがよく回るし,常用するには辛すぎた
Macの認定整備済品リストから要件を満たすものを列挙させている
取り敢えず価格の安い順で確認だ
M1 ProとM1 MaxではCPUのCore数は全く同じなので比較しない
ただ「M1 ProかM1 Maxか」と「SSDの容量」「RAMの容量」と「SSDの速度」「RAMの速度」に関係があるらしい(俺はLPDDR5-6400というだけで満足)
最安モデルは318800円
GPU 16Core,RAM 32GB,SSD 512GB
ちなみにこの記事を書いた時点でシルバーは売り切れている
次に来るのは339800円…だが,
こっちはGPU 24Core,RAM 32GB,SSD 512GB
こっちはGPU 16Core,RAM 32GB,SSD 1TB
つまりどちらかを選んでねということである
その次に来るのは354800円
そして問題なのがその次の360800円
これはGPU 24Core,RAM 32GB,SSD 1TB
これはGPU 32Core,RAM 32GB,SSD 512GB
…俺の読み間違えでなければ,性能と価格の順序がここで崩壊していることになる…なぜ?
ちなみに次は380800円なのだが,
これはGPU 24Core,RAM 64GB,SSD 512GB www.apple.com
これはGPU 16Core,RAM 32GB,SSD 2TB
となっており,そしてここから先のGPU 32Coreを持つオプションは一気に値上がりする,いずれもSSDとRAMの増設の影響をモロに受けてるのかもしれない
つまり,これ
が良いと判断した
my new gear...
いやまったくわからん,どうしてこうなってるのかなにも想像がつかん
バグかと思ったが頼んで届いたらまんまのスペックだったし夢でもない
SoCだし普通に考えればチップまでイジる再整備なんてあるわけがない
だからパーツの価格がどうこうなんてロジックは存在しないはずだろう
ともかく性能が上位互換で尚且つ安価なら明らかに買うべき品物である
MBP2016と比較して
そうらしいが,取り敢えず届いてすぐにhomebrew
とsmartctl
を最速で導入して,そのままSSDのSMART情報を引っこ抜いてきた,その時の結果を貼っておく
% smartctl -x /dev/disk0 smartctl 7.3 2022-02-28 r5338 [Darwin 22.1.0 arm64] (local build) Copyright (C) 2002-22, Bruce Allen, Christian Franke, www.smartmontools.org === START OF INFORMATION SECTION === Model Number: APPLE SSD AP1024R Serial Number: 0ba01912c148e807 Firmware Version: 873.40.4 PCI Vendor/Subsystem ID: 0x106b IEEE OUI Identifier: 0x000000 Controller ID: 0 NVMe Version: <1.2 Number of Namespaces: 3 Local Time is: Tue Mar 7 16:57:40 2023 JST Firmware Updates (0x02): 1 Slot Optional Admin Commands (0x0004): Frmw_DL Optional NVM Commands (0x0004): DS_Mngmt Maximum Data Transfer Size: 256 Pages Supported Power States St Op Max Active Idle RL RT WL WT Ent_Lat Ex_Lat 0 + 0.00W - - 0 0 0 0 0 0 === START OF SMART DATA SECTION === SMART overall-health self-assessment test result: PASSED SMART/Health Information (NVMe Log 0x02) Critical Warning: 0x00 Temperature: 25 Celsius Available Spare: 100% Available Spare Threshold: 99% Percentage Used: 0% Data Units Read: 1,246,833 [638 GB] Data Units Written: 974,955 [499 GB] Host Read Commands: 21,527,048 Host Write Commands: 11,271,572 Controller Busy Time: 0 Power Cycles: 348 Power On Hours: 8 Unsafe Shutdowns: 18 Media and Data Integrity Errors: 0 Error Information Log Entries: 0 Read 1 entries from Error Information Log failed: GetLogPage failed: system=0x38, sub=0x0, code=745
Appleによって1度リセットされた上で動作テスト等などが行われたのか,それとも前の使用者の状態をそのまま引き継いだのか,ちょっとこれではわからない
総Write量が500GBだが,これは明らかにmacOS Venturaのサイズ(13GB)より大きく,Appleがそれだけテストしているとも思えない,訊くしかなさそうだ…
#include <iostream> using namespace std; void itakogei(){ cout << "再帰関数の大川隆法です.スゥ…「"; itakogei(); cout << "」" << endl; } int main(void){ itakogei(); }
※初歩的な勘違いをしていたのでメモ
といってもリンクができないだけで分割コンパイルはできる(できてしまう)
#pragma once namespace Hoge{ typedef float hoge; hoge setHoge(); void getHoge(hoge value); };
#include <iostream> #include "hoge.hpp" using namespace std; using namespace Hoge; hoge setHoge(){ return ((hoge)10); } void getHoge(hoge value){ cout << value << endl; }
#include <iostream> #include "hoge.hpp" using namespace Hoge; int main(){ hoge x = setHoge(); // x = 10 getHoge(x); // print 10 return 0; }
make: clang++ -std=c++20 -c hoge.cpp main.cpp nm hoge.o > hoge.sym nm main.o > main.sym clang++ hoge.o main.o -o test
clang++ -std=c++20 -c hoge.cpp main.cpp nm hoge.o > hoge.sym nm main.o > main.sym clang++ hoge.o main.o -o test Undefined symbols for architecture x86_64: "Hoge::getHoge(float)", referenced from: _main in main.o "Hoge::setHoge()", referenced from: _main in main.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [make] Error 1
上のスクリプトで分割コンパイルすると,それぞれ#include "hoge.hpp"
が展開された上で翻訳単位としてhoge
とmain
の2つが発生して,それぞれが処理されてシンボルテーブルを持つオブジェクトとして出てくる
main
側はHoge
周りの実装をしていないため,hoge.hpp
の宣言した内容に期待して,名前空間Hoge
を含めたシンボルをあらかじめ設定する
ゆえにhoge
側は名前空間Hoge
を含めたシンボルを実体に持つような実装が期待されており,そうでなければリンク時に名前を解決できず失敗する
ソース側でusing namespace Hoge
を利用して(名前空間の解決の記法を省略して)実装することは不可能であり,それはコンパイラが名前空間の探索と適切な配置よりも先に勝手に大域的な配置をしてしまうためである…
なんでそうなのかは知りませんが,歴史的な経緯とかあるのでしょうか?やっぱり外部リンケージがデフォルトな言語だからなんですかね,extern
とconst
も難解すぎてこのままではstatic
おじさんになってしまう…
hoge
側nm hoge.o | grep Hoge
0000000000000010 T __Z7getHogef 0000000000000000 T __Z7setHogev
main
側nm main.o | grep Hoge
U __ZN4Hoge7getHogeEf U __ZN4Hoge7setHogeEv
namespace Hoge{}
の中に実装を書く多分これが一番楽だと思います,ただしクソデカネストが許容できる場合の話,俺は辛い耐えられない
#include <iostream> #include "hoge.hpp" using namespace std; using namespace Hoge; namespace Hoge{ hoge setHoge(){ return ((hoge)10); } void getHoge(hoge value){ cout << value << endl; } }
Hoge::
をつけるusing namespace Hoge;
しつつクソデカネストを使わないなら,多分これが一番楽だと思います
また宣言されたtypedef
やclass
の名前スコープを無視できる,人によっては折衷案に見える?
#include <iostream> #include "hoge.hpp" using namespace std; using namespace Hoge; hoge Hoge::setHoge(){ return ((hoge)10); } void Hoge::getHoge(hoge value){ cout << value << endl; }
諸事情あってc++でクラス設計をやるようになったが,なんというかアルゴリズム的なものを全く使わないタイプの実装ばっかりやっており,せいぜい自作の行列クラスをどう設計するか程度だった
普段の作業に飽きてきてc++そのものが嫌になり始めたので,気分転換にとでもAtCoderの練習コースで遊び始めた
つまりはマジモンの初心者なので,今までまともに扱うことのなかったシェルのIOについての学習からやっている
これのEX22までやって肩慣らしを始めたつもりでいる
…結論から言うと「やべぇアルゴリズムなんもわからんかも」という状態であり,そもそも組込実装とは要求されている要件が違いすぎるためである
クラス設計にそういう要素を組み込むのは確かに面白いと感じたが,それ以上に問題がハードになっていくにつれてこの作業に命を賭けるのは正直キツいよなぁと思った
分割コンパイルでモジュール開発をする場合は,ライブラリのシンボル指向実装とinclude
地獄の回避可能なヘッダ記述手法の都合から,モジュールが異なる(レイヤが1つ下の)自作クラスをメンバ変数に持つなら,実体ではなくポインタで持った方が良く,かつそれらはnew
・delete
を使用してメモリ管理をちゃんと実装し,コンストラクタもデストラクタも確認するべし,的な結論に至った(c++98
縛りゆえスマートポインタ不使用)
しかしモジュールの開発においては,同一レイヤのレベルで自作クラスを実装して,そのまま自作クラスのメンバ変数に組み込む,みたいな場合があるかもしれない(,むしろそれが基本的なクラス設計のやり方なのでは…?)
new
・delete
する癖をつけた方が良いかもしれない=
の定義を確認するべし
x
」を抱えるクラスy
」をオブジェクトにする場合,クラスy
のコンストラクタが走る前にクラスx
のデフォルトコンストラクタが走る,自作クラスを実体で持つ限りこの挙動は避けられないy
のコンストラクタ内でクラスx
のコンストラクタを叩き,その結果をメンバ変数に=
で接続すると,クラスの初期化と同様に反映できる気もするが,これは初期化の文法ではなく代入の文法として動作する
=
が曖昧な自作クラスを実体としてメンバ変数に持つと予期せぬ動作が起きるかも…
=
を定義した方が,実装の責任境界が明確だし後で他のクラスに使われる時も好都合だしで生産性があるコピー代入演算子のみを扱う,ムーブ代入演算子は扱わない ただし速度向上を考えたら後者の方が良いのかもしれない…
=
のオーバーロードが必要なケースnew
・delete
またはmalloc
・free
でメモリ確保したポインタを持ってその中でデータを保持している場合,ポインタをコピーするのかポインタの中身をコピーするのかちゃんと考えて実装しよう. ├── bin │ └── main ├── libDataBase │ ├── inc │ │ └── libDataBase.hpp │ ├── lib │ │ └── liblibDataBase.a │ └── src │ ├── framework.cpp │ ├── framework.hpp │ ├── interface.cpp │ └── interface.hpp ├── makefile └── src └── main.cpp
SHELL = /bin/zsh MAIN_SRC = src/main.cpp MAIN_OBJ = main.o MAIN_BIN = bin/main GCC_BIN = clang++ GCC_FLG = -std=c++11 -O2 make : make libDataBase make main libDataBase : FORCE $(call setAllVar,libDataBase) $(GCC_BIN) $(GCC_FLG) -c $(libDataBase_SRC) @ar cr $(libDataBase_OBJ) *.o @rm -f *.o $(shell echo '#pragma once' > $(libDataBase_REP);) $(foreach hed,$(libDataBase_HED),$(shell echo '#include "$(hed)"' >> $(libDataBase_REP);)) main : FORCE $(call setRefVar,libDataBase) $(GCC_BIN) $(GCC_FLG) -c $(libDataBase_INC) $(MAIN_SRC) $(GCC_BIN) $(GCC_FLG) -o $(MAIN_BIN) $(MAIN_OBJ) $(libDataBase_LIB) @rm -f *.o FORCE : define setAllVar $(eval $1_HED = $(notdir $(wildcard $1/src/*.hpp))) $(eval $1_SRC = $(wildcard $1/src/*.cpp)) $(eval $1_OBJ = $1/lib/lib$1.a) $(eval $1_REP = $1/inc/$1.hpp) $(eval $1_INC = -I$1/inc -I$1/src) $(eval $1_LIB = -L$1/lib -l$1) endef define setRefVar $(eval $1_OBJ = $1/lib/lib$1.a) $(eval $1_REF = $1/inc/$1.hpp) $(eval $1_INC = -I$1/inc -I$1/src) $(eval $1_LIB = -L$1/lib -l$1) endef
void operator=(const claassName& arg)
でやった
const
をつけるときは先頭(戻り値)ではなく末尾
const
をつける関数に意味があるのかは正直よくわかっていないconst
をつけると,引数arg
を変更しないという宣言になるが,その処理でarg
の持つ関数を呼び出す場合は,それがarg
自身を変更しないことをコード上で保証する必要があるため#pragma once #include <string> namespace database{ class framework{ private: int ID; std::string Name; int Year; public: framework(); framework(int id); framework(const framework &arg); ~framework(); void operator=(const framework &arg); void setName(std::string name); void setYear(int year); int getID() const; std::string getName() const; int getYear() const; }; }
const
に設定したgetXXX()
を使用してconst
で引数を取れるコピー代入演算子を作成する#include <iostream> #include "framework.hpp" using namespace std; using namespace database; framework::framework(){ cout << " framework: Default Constructor, ID: " << -1 << endl; ID = -1; Name = ""; Year = 0; } framework::framework(int id){ cout << " framework: Normal Constructor, ID: " << id << endl; ID = id; Name = ""; Year = 0; } framework::framework(const framework &arg){ cout << " framework: Copy Constructor, ID: " << ID << endl; ID = arg.getID(); Name = arg.getName(); Year = arg.getYear(); } framework::~framework(){ cout << " framework: Destructor, ID: " << ID << endl; } void framework::operator=(const framework& arg){ cout << " framework: Substitute, ID: " << ID << " -> " << arg.ID << endl; ID = arg.getID(); Name = arg.getName(); Year = arg.getYear(); } void framework::setName(string name){ cout << " Set Name: " << name << endl; Name = name; } void framework::setYear(int year){ cout << " Set Year: " << year << endl; Year = year; } int framework::getID() const{ cout << " Get ID: " << ID << endl; return ID; } string framework::getName() const{ cout << " Get Name: " << Name << endl; return Name; } int framework::getYear() const{ cout << " Get Year: " << Year << endl; return Year; }
<map>
を使ってみた,あとイテレータを使用せずforeach
を使いたかったので-std=c++11
を指定したmap
自体はint
なid
とframework*
なデータを持つteamData
に使用
addMember
,eraseMember
,showMember
をAPIみたいにして実装_id_latest
は吐き出したID
の最新の値を指す,ガバガバ実装なのは許して#pragma once #include <string> #include <map> #include "framework.hpp" namespace database{ class interface{ private: framework myData; std::map<int, framework*> teamData; int _id_latest; public: interface(); interface(std::string name, int year); ~interface(); int addMember(std::string name, int year); void eraseMember(int id); void showMember(int id); }; }
map
のデータ構造がよくわからなかったので,ポインタで持つ処理を採用した
c++11
を選んだ
for (const auto& member: map){}
が書けるのはc+11
以降…?auto
のところはちょっと面倒だったので厳密な書き方をしなかっただけ#include <iostream> #include "interface.hpp" using namespace std; using namespace database; interface::interface(){ cout << "interface: Default Constructor" << endl; } interface::interface(string name, int year){ cout << "interface: Normal Constructor" << endl; myData = framework(0); myData.setName(name); myData.setYear(year); _id_latest = 0; interface::addMember(name, year); } interface::~interface(){ cout << "interface: Destructor" << endl; for (const auto& member: teamData){ delete (member.second); } teamData.clear(); } int interface::addMember(string name, int year){ cout << "Add Team Member" << endl; ++_id_latest; teamData[_id_latest] = new framework(_id_latest); teamData[_id_latest]->setName(name); teamData[_id_latest]->setYear(year); return _id_latest; } void interface::eraseMember(int id){ cout << "Erase Team Member" << endl; delete (teamData[id]); teamData.erase(id); } void interface::showMember(int id){ cout << "Show Team Member" << endl; teamData[id]->getID(); teamData[id]->getName(); teamData[id]->getYear(); }
#include <iostream> #include <string> #include "libDataBase.hpp" using namespace std; using namespace database; int main(){ cout << "User name and year" << endl; string name; cin >> name; int year; cin >> year; interface mydatabase = interface(name ,year); int Aiko_id = mydatabase.addMember("敬宮愛子", 2001); int Hisahito_id = mydatabase.addMember("秋篠宮悠仁", 2006); mydatabase.showMember(Aiko_id); mydatabase.showMember(Hisahito_id); mydatabase.eraseMember(Aiko_id); mydatabase.eraseMember(Hisahito_id); };
% bin/main User name and year Soluna_Eureka 2000 framework: Default Constructor, ID: -1 interface: Normal Constructor framework: Normal Constructor, ID: 0 framework: Substitute, ID: -1 -> 0 Get ID: 0 Get Name: Get Year: 0 framework: Destructor, ID: 0 Set Name: Soluna_Eureka Set Year: 2000 Add Team Member framework: Normal Constructor, ID: 1 Set Name: Soluna_Eureka Set Year: 2000 Add Team Member framework: Normal Constructor, ID: 2 Set Name: 敬宮愛子 Set Year: 2001 Add Team Member framework: Normal Constructor, ID: 3 Set Name: 秋篠宮悠仁 Set Year: 2006 Show Team Member Get ID: 2 Get Name: 敬宮愛子 Get Year: 2001 Show Team Member Get ID: 3 Get Name: 秋篠宮悠仁 Get Year: 2006 Erase Team Member framework: Destructor, ID: 2 Erase Team Member framework: Destructor, ID: 3 interface: Destructor framework: Destructor, ID: 1 framework: Destructor, ID: 0
見た感じ問題なく動いてるからよし
framework: Default Constructor, ID: -1 interface: Normal Constructor framework: Normal Constructor, ID: 0 framework: Substitute, ID: -1 -> 0 Get ID: 0 Get Name: Get Year: 0 framework: Destructor, ID: 0 Set Name: Soluna_Eureka Set Year: 2000
まずframework
のデフォルトコンストラクタが起爆して,次にinterface
のコンストラクタが起爆する
そして新たにframework
コンストラクタが起爆して,生成されたオブジェクト(右辺値)のコピー代入演算子によるオブジェクト(左辺値としてのメンバ変数)への代入が発生し,最後にデストラクタでオブジェクト(右辺値)が消滅する
Add Team Member framework: Normal Constructor, ID: 1 Set Name: Soluna_Eureka Set Year: 2000 Add Team Member framework: Normal Constructor, ID: 2 Set Name: 敬宮愛子 Set Year: 2001 Add Team Member framework: Normal Constructor, ID: 3 Set Name: 秋篠宮悠仁 Set Year: 2006
ここではコンストラクタのついでにadd
を使ってmap
のnew framework
に登録している
愛子様,悠仁様,両親王陛下も.わたくしと全く同じ動作をされておりますが,全く同じ関数をご使用賜れておられるゆえ,当然のことだろうと存じ上げます(番号の順番はスルーしてくれ)
Erase Team Member framework: Destructor, ID: 2 Erase Team Member framework: Destructor, ID: 3 interface: Destructor framework: Destructor, ID: 1 framework: Destructor, ID: 0
そしてerase
もデストラクタもちゃんと動いている,撃ち漏らしはないように思える
<map>
と<string>
を初めて使った,しかしmap
はともかくstring
は日本語をそのまま使えてしまっているが,文字コード的に本当にコレで良いのかどうか疑問,ぶっちゃけまだ解決しきった問題でもなさそうだけど
あとポインタで持った方がコピーコスト少ないし拡張性あるし結局はポインタを使う方が良いという結論に至った
作ってみたけどコピー代入演算子の引数は参照渡しが使えなかった,だって
z = A*x + B*y
とかやる場合だと,operator*
やoperator+
の返り値は行列クラスそのものになるし,これをそのまんまoperator=
で受け取るには値渡ししかない
参照渡しと値渡しそれぞれのコピー代入演算子は,クラスで実装できてもコードで呼び出すときは曖昧さでエラーを吐くので,ユーザーは使い分けもできない
引数のconst
の厳密な管理も辛い,しかしこっちはちゃんとやるべきだった,マシなコーディング規約を考えて修正したいとは思ってる
c++98
を想定してるc++11
以降の機能なのでmakefile
の改造
make
の文法なのかこれもうわかんねぇなmake
の機能だけで色々やろうとしたが個人的には無理だった
x
をメンバ変数に持つクラスy
を定義するヘッダファイルでは,前方宣言でx
を定義してinclude
の多重ロードを防止する
x
を定義してinclude
せずに,ソースファイルではx
を定義するヘッダファイルをinclude
するx
」を抱えるクラスy
」を抱えるクラスz
」を定義する時にヘッダファイルに依存関係を全て表示すると,y
を定義するヘッダファイルに加えてy
を経由してx
を定義するヘッダファイルまでロードする,といった多重インクルードが発生する
include path
の管理が壊れるinclude
するならOK,ただしそれでもinclude path
には十分に注意するy
はクラスx
をメンバ変数に持つが,コンパイラの都合によって実体ではなくポインタで持つ必要があり
x
」を抱えるクラスy
」を抱えるクラスz
」の実装をコンパイルする際は,多重インクルードが阻止されているためにx
のサイズが不定となり,つまりy
のサイズも不定となり,そしてx
のサイズも不定となるため,普通にエラーを吐かれる
c++98
ではnew
とdelete
を自力で管理しないとメモリリークするので,気をつけるべしinclude
の依存関係に一致しないので.リンカに渡すパスの管理が面倒run-time-support
のライブラリとして提供されている場合があるらしい以下は一例
. ├── bin │ └── main ├── libA │ ├── inc │ │ └── libA.hpp │ ├── lib │ │ └── liblibA.a │ └── src │ ├── clsA.cpp │ └── clsA.hpp ├── libB │ ├── inc │ │ └── libB.hpp │ ├── lib │ │ └── liblibB.a │ └── src │ ├── clsB.cpp │ └── clsB.hpp ├── makefile └── src └── main.cpp
inc
とlib
とsrc
に分割src
にはソースファイルとヘッダファイルを設置lib
には静的ライブラリを設置inc
のはsrc
にあるヘッダファイルを全てinclude
した代表ヘッダファイルを設置
makefile
で自動的に生成するinclude path
はsrc
の方にも通す,代表ヘッダファイルが呼び出すのでmakefile
の改造以下は一例
SHELL = /bin/zsh MAIN_SRC = src/main.cpp MAIN_OBJ = main.o MAIN_BIN = bin/main GCC_BIN = clang++ GCC_FLG = -std=c++98 -O2 make : make libA make libB make main libA : FORCE $(call setAllVar,libA) $(GCC_BIN) $(GCC_FLG) -c $(libA_SRC) @ar cr $(libA_OBJ) *.o @rm -f *.o $(shell echo '#pragma once' > $(libA_REP);) $(foreach hed,$(libA_HED),$(shell echo '#include "$(hed)"' >> $(libA_REP);)) libB : FORCE $(call setAllVar,libB) $(call setRefVar,libA) $(GCC_BIN) $(GCC_FLG) -c $(libA_INC) $(libB_SRC) @ar x $(libA_OBJ) @ar cr $(libB_OBJ) *.o @rm -f *.o __.* $(shell echo '#pragma once' > $(libB_REP);) $(foreach hed,$(libB_HED),$(shell echo '#include "$(hed)"' >> $(libB_REP);)) main : FORCE $(call setRefVar,libB) $(GCC_BIN) $(GCC_FLG) -c $(libB_INC) $(MAIN_SRC) @ar x $(libB_OBJ) $(GCC_BIN) $(GCC_FLG) -o $(MAIN_BIN) $(MAIN_OBJ) $(libB_LIB) @rm -f *.o __.* FORCE : define setAllVar $(eval $1_HED = $(notdir $(wildcard $1/src/*.hpp))) $(eval $1_SRC = $(wildcard $1/src/*.cpp)) $(eval $1_OBJ = $1/lib/lib$1.a) $(eval $1_REP = $1/inc/$1.hpp) $(eval $1_INC = -I$1/inc -I$1/src) $(eval $1_LIB = -L$1/lib -l$1) endef define setRefVar $(eval $1_OBJ = $1/lib/lib$1.a) $(eval $1_REF = $1/inc/$1.hpp) $(eval $1_INC = -I$1/inc -I$1/src) $(eval $1_LIB = -L$1/lib -l$1) endef
shell
はzsh
を指定する
make
の機能を叩くのは無理
$(foreach)
して$(shell echo)
したらできた…FORCE
を使って常に強制的にmake
を実行させる
-L
は静的ライブラリの探索パスでリンク時に使う,-I
はヘッダファイルの探索パスでコンパイル時に使う-L
と一緒に使う-l
はライブラリを指定するが(lib)libA.a
みたいに先頭のlib
が削れるらしいバラしてマージするパターンを実装した
ar x libName
でバラしてar cr libName *.o
でマージしてrm *.o __.*
で一時ファイルを消す
macOSに入るcommand line tool
のclang++
は__.SYMDEF
なるものを出すが,たぶんgnu
のclang++
でも同じことが起きる
見た感じシンボルのリスト(が短縮されたもの)が入ってるテキストファイルっぽかったが,用途がよくわからない,調べる必要があるかも
以下は一例
libA
#pragma once namespace libA{ class clsA{ private: int __Num; protected: int _Num; public: clsA(); ~clsA(); int Num; void aLog(); }; }
#include <iostream> #include "clsA.hpp" using namespace std; using namespace libA; clsA::clsA(){ cout << "construct A" << endl; __Num = 0; _Num = 1; Num = 2; } clsA::~clsA(){ cout << "destruct A" << endl; } void clsA::aLog(){ cout << " log from A" << endl; cout << " private num: " << __Num << endl; cout << " protected num: " << _Num << endl; cout << " public num: " << Num << endl; }
libB
#pragma once namespace libA{ class clsA; } namespace libB{ class clsB{ private: libA::clsA* __aObj; protected: libA::clsA* _aObj; public: libA::clsA* aObj; clsB(); ~clsB(); void bLog(); }; }
#include <iostream> #include "libA.hpp" #include "clsB.hpp" using namespace std; using namespace libA; using namespace libB; clsB::clsB(){ cout << "construct B" << endl; __aObj = new clsA(); _aObj = new clsA(); aObj = new clsA(); } clsB::~clsB(){ cout << "destruct B" << endl; delete __aObj; delete _aObj; delete aObj; } void clsB::bLog(){ cout << "log from B" << endl; cout << " private A:" << endl; __aObj->aLog(); cout << " protected A:" << endl; _aObj->aLog(); cout << " public A:" << endl; aObj->aLog(); }
new
とdelete
でメモリを管理する
c++11
以降はユニークポインタを使うべき?.
ではなく->
で変数やメソッドを呼び出すmain
#include <iostream> #include "libB.hpp" using namespace std; using namespace libB; int main(){ clsB* bObj = new clsB();; bObj->bLog(); delete bObj; };
new
とdelete
を使った方がコーディング規約的に楽かもmain
からは2つ下のレイヤのclsA
の変数とメソッドを叩けない
% make make libA clang++ -std=c++98 -O2 -c libA/src/clsA.cpp make libB clang++ -std=c++98 -O2 -c -IlibA/inc -IlibA/src libB/src/clsB.cpp make main clang++ -std=c++98 -O2 -c -IlibB/inc -IlibB/src src/main.cpp clang++ -std=c++98 -O2 -o bin/main main.o -LlibB/lib -llibB % bin/main construct B construct A construct A construct A log from B private A: log from A private num: 0 protected num: 1 public num: 2 protected A: log from A private num: 0 protected num: 1 public num: 2 public A: log from A private num: 0 protected num: 1 public num: 2 destruct B destruct A destruct A destruct A
過酷環境の組込実装では初期化と割込制御をint main(){}
とinterrupt void xxx(){}
のように実装するので,例えば制御器は大域変数を介して動作する必要がある
それぞれの関数や変数は別のソースに書いてextern
してまとめてコンパイルすれば使えるが,そういうやり方ではいつか地獄を見るのでよろしくないとされる
では大域変数として制御器の機能を持つ自作クラスをオブジェクト化するとどうなるのかと言えば,(処理系によって違うが)main
の実行前の処理にオブジェクトのコンストラクタが走るように登録されたり,実行後の処理にデストラクタが走るように登録されたりする,これもrun time support
のライブラリで提供される機能となる
しかし実質的にmain
が初期化ルーチンとなっているなら,クラスのポインタを大域変数に置きつつ後でnew
で実体化しても良さそうなのだが,するとdelete
ってどうやって登録すれば良いのだろうか…?
macOS Montereyならみんなできるはず?
こんな項目あったっけ…
Dockのサイズが規定値内に戻されるので
defaults write com.apple.dock largesize -int 256 | killall Dock
しよう
ついにVenturaからこの世代がサポートを打ち切られた 2018年に有楽町ビックカメラで10万くらい安く売られてたのを現物で買ったUSキー持ちの正規品 ディスプレイもスピーカーも元気だけどキーボードは完全に壊れちゃったので外付けを使っている 最近は起動が遅くディスクもヤバい,次どうしようか,M2 Airは為替がアレだしMacはSSD高い… (intelチップ2016 Late世代でもtouch barつきモデルはSSDの換装はできないらしいので)