読者です 読者をやめる 読者になる 読者になる

ボレロ村上 - ENiyGmaA Code

中3女子です。

test-pred_warning.cpp

↓は2chのBoostスレでの自分の書き込みです。
http://pc12.2ch.net/test/read.cgi/tech/1251446016/373


のBOOST_STATIC_WARNINGは、
クラステンプレートの中で働かなかったりとか、いろいろあります。
そういった条件もいまいちわからない。
まあ、もともとテンプレートメタで意図的にwarning出そうとしたら、
ポータビリティゼロな方法しかないわけで。


それでも何とかならないか、と思って書いてみたのが
Sprig.PredWarning と Sprig.StaticWarning
どこに書いてもちゃんとチェックが働きます。
ただしMSVC限定。GCCではまるで働かず。


SPRIG_PRED_WARNING( (F) )は、BOOST_MPL_ASSERT( (F) )と同じように書きます。
SPRIG_STATIC_WARNING(B)は、BOOST_STATIC_ASSERT(B)と同じように書きます。


実装は、BOOST_MPL_ASSERTなどで使われている、
sizeof(オーバーロードされた関数を呼ぶ式)の値で引数のチェックを行う
テクニックを仕様しています。

  • test-pred_warning.cpp
#include <boost/mpl/bool.hpp>
#include <sprig/pred_warning.hpp>

int main(int argc, char* argv[]) {
    SPRIG_PRED_WARNING((boost::mpl::true_));
    SPRIG_PRED_WARNING((boost::mpl::false_));

    return 0;
}
コンパイルしています...
test-pred_check.cpp
l:\project\vc9\test\test\test-pred_warning.cpp(6) : warning C4305: '初期化中' :
 'sprig::PRED_WARNING_CHECK' から 'sprig::PRED_WARNING_FAILED' へ切り詰めます。

sprig::PRED_WARNING_CHECKはstd::size_tのtypedefで、
sprig::PRED_WARNING_FAILEDはboolのtypedefです。


以下はSPRIG_PRED_WARNINGの実装の一部

#define SPRIG_PRED_WARNING(PRED) \
    static sprig::PRED_WARNING_FAILED BOOST_PP_CAT(pred_warning_, __LINE__) \
        = (sprig::PRED_WARNING_CHECK)SPRIG_PRED_CHECK(PRED)

SPRIG_PRED_CHECK(PRED)は、PREDが真ならばsizeof(char)/* == 1 */を返し、
PREDが偽ならば0と1以外の値を返します。


std::size_tからboolへの暗黙の変換が行われるわけですが、
VCコンパイラは型変換によってオーバーフローが起こる場合、warning C4305を生成します。
通常(ランタイムコード)は、「オーバーフローが起こる可能性のある場合」に警告が出ますが、
コンパイル時の変換の場合、「オーバーフローが実際に起こった場合」に警告を出してくれます。


上記の場合だと、sizeof(char)/* == true*/からboolへの変換では警告になりませんが、
2以上の値からboolへの変換だとオーバーフローが起こり警告が出るわけです。
(もちろん、これらの話はほとんどMSVC前提のこと)


C++0xではstatic_assertが標準に入ったけど、
更に次の規格(あれば)ではstatic_warningも入ってほしいところ。