「コードの言語の意識」について、私はノー良くありますあなたはこのような何かを行うことができブーストMPLと例えば
Lispとそのマクロ機能、特にCommon Lispよりも見たことがあります。しかし、そこでの取引は、オブジェクトの型がコンパイル時またはマクロ展開時に知られていない時間がほとんどです。リテラルでは型が分かっているので、オブジェクトがリテラルかどうかを調べるテストを行う攻撃的なマクロの例を見つけることができます。実行時型検査の場合
ここ数年前にCLLIBライブラリ(CLOCCライブラリの一部)から変更した例です。目的は、接頭辞ストリングを一致する接頭辞を持つ他の文字列から切り捨てる機能を提供することです。プレフィックスはマクロ展開時に分かっているかもしれませんし、そうでないかもしれません。可能であれば、最適化することができます。接頭辞の長さを最初に計算し、それをリテラルとして埋め込み、生成された関数の呼び出しごとに再計算されないようにします。最初はマクロが大変ですが、実際に生成されるコードは小さいです。
(defmacro after-prefix-core (comparison-op prefix string &optional length)
"Similar to cllib:string-beg-with-cs."
(flet ((chop (prefix prefix-length string string-length)
`(when (and (>= ,string-length ,prefix-length)
(,comparison-op ,prefix ,string :end2 ,prefix-length))
(subseq ,string ,prefix-length ,string-length))))
(let* ((gstring (gensym "STRING-"))
(gstring-length (gensym "STRING-LENGTH-")))
`(let* ((,gstring ,string)
(,gstring-length ,(or length `(length ,gstring))))
,(if (stringp prefix)
;; Constant -- length known at expansion time.
(let ((prefix-length (length prefix)))
(chop prefix prefix-length gstring gstring-length))
;; Other form -- length not known at expansion time.
(let ((gprefix (gensym "PREFIX-"))
(gprefix-length (gensym "PREFIX-LENGTH-")))
`(let* ((,gprefix ,prefix)
(,gprefix-length (length ,gprefix)))
,(chop gprefix gprefix-length gstring gstring-length))))))))
(defmacro after-prefix (prefix string &optional length)
"Similar to cllib:string-beg-with."
`(after-prefix-core string-equal ,prefix ,string ,length))
(defmacro after-prefix-cs (prefix string &optional length)
"Similar to cllib:string-beg-with-cs."
`(after-prefix-core string= ,prefix ,string ,length))
は途中でフォーム
(if (stringp prefix)
を参照してください?これは、マクロ展開時の最初の引数を検査しています。引数がリテラルかシンボルかによっては、型がわかっていてもいなくてもかまいません。型がシンボルの場合、は実行時まで他の値を指す変数として再考する必要があると仮定してと仮定します。変数#:PREFIX-LENGTH-5343
を変数#:PREFIX-5342
にここにバインドさFOO
の計算された長さ、にバインドされていることを
(LET* ((#:STRING-5340 BAR) (#:STRING-LENGTH-5341 (LENGTH #:STRING-5340)))
(LET* ((#:PREFIX-5342 FOO) (#:PREFIX-LENGTH-5343 (LENGTH #:PREFIX-5342)))
(WHEN
(AND (>= #:STRING-LENGTH-5341 #:PREFIX-LENGTH-5343)
(STRING-EQUAL #:PREFIX-5342 #:STRING-5340 :END2 #:PREFIX-LENGTH-5343))
(SUBSEQ #:STRING-5340 #:PREFIX-LENGTH-5343 #:STRING-LENGTH-5341))))
注:
はここでフォーム(after-prefix foo bar)
のための拡張です。
今プレフィックスが今リテラル文字列でフォーム(after-prefix "foo" bar)
、のための拡張を見て:
(LET* ((#:STRING-5463 BAR) (#:STRING-LENGTH-5464 (LENGTH #:STRING-5463)))
(WHEN (AND (>= #:STRING-LENGTH-5464 3) (STRING-EQUAL "foo" #:STRING-5463 :END2 3))
(SUBSEQ #:STRING-5463 3 #:STRING-LENGTH-5464)))
今何コンピューティングは、「foo」というの長さはありません。それは3としてインライン化されています。
この例ではあまりにも多くの作業のように見えるかもしれませんが、そのようなことを行うことができることはあなたの質問opinesとして良い力です。
多くのCおよびC++コンパイラは、コンパイル時に 'if'の式が判別できれば、未使用のコードを削除します。あなたの質問に完全に答えるかどうかは分かりません。 –
いいえ - 静的なifの一部のブロックのコードが有効でないため、上記の例はコンパイルされません。例えば。 Tがint型の場合、value .__ repr __()はコンパイルエラーです。 – Grumdrig
上記をコンパイルするには、「静的if(typeof(value .__ repr__))」)を作成する必要があります。または "静的if(__ traits(コンパイル、値.__ repr__))")。 – Baxissimo