2015-11-18 1 views
10

私は何らかの形で無効にすることを試みています(私の経験では、誤って整数を文字列に割り当てて、微妙で困難なバグを追跡する場合にのみ使用されます)恐ろしいstd::string::operator=(char)オーバーロードを非難しました。私のプロジェクトで標準ライブラリ*の関数/メソッドを非推奨(または完全に無効)としてマークする方法はありますか?

私が試した:すでに<string>として失敗したことで、静的アサートとの明示的な特殊

#include <string> 
#include <type_traits> 

template<> std::basic_string<char> &std::basic_string<char>::operator=(char c) { 
    static_assert(false, "Don't use this!"); 
} 

std::string

  • [[deprecated]]属性の明示的なインスタンス化を行い、

    • 上記と同様の宣言に様々な地位で適用される。私が試したポジションは、合理的な結果をもたらすとは思われませんでした。

    • =deleteこれは上記の理由で失敗します。
    • 同じプロジェクトで、同様のプロジェクトで、--wrapldリンカオプションを使用して、迷惑行為setlocaleの使用状況に関するランタイムチェックを行っていますが、これはテンプレートとインラインメソッドであるという事実が複雑になります。質問に今

    :あなたが変更することはできませんライブラリで:

    • は何とか標準ライブラリ内の任意の関数やメソッド(読み(=deleteで起こるように)無効にするための標準的な方法がありますヘッダーの宣言)?
    • 上記のとおりですが、無効にする代わりに、警告を追加します([[deprecated]]の場合と同様)。
    • 標準的な方法には失敗しました。何かg ++固有のものがありますか?
    • "一般的な"(任意のメソッド、クラス、関数などに適用可能)解決策がない場合、この特定のケースに適用できるものがありますか(=可能であればテンプレートクラスのメソッドを無効にします。特定のインスタンス化だけでも)?
  • +1

    静的なアサートまたは削除された関数を使用しようとしている場合は、おかしな定義があります。 –

    +0

    @JonathanWakely: "廃止予定または全部停止";しかし、私が考えている限り、それは本質的に同じですが、とにかくそのような警告に '-Werror'を使用すると、その代入演算子を使用する正当な理由はありません(' gets 'または文字列リテラル=>' 'char *' 'の変換)を使用します。 –

    答えて

    4

    次のコンパイラ/リンカオプションを使用することができます説明

    $ g++ -O0 test.cpp -Wl,--wrap=_ZNSsaSEc 
    

    を:

    $ echo _ZNSsaSEc | c++filt 
    std::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(char) 
    

    _ZNSsaSEcがあなたの問題の関数の装飾の名前です。 -Wlコンパイラオプションはリンカにオプションを渡すことです。

    そして、--wrap=<symbol>リンカオプションは、任意のシンボルへの参照を代替__wrap_<symbol>に変換します。あなたは(たぶん)__wrap__ZNSsaSEcという名前の関数を定義していないので、あなたは素敵なリンカエラーが発生します。

    test.cpp:(.text+0x26): undefined reference to `__wrap__ZNSsaSEc' 
    

    -O0は、最適化を無効にし、機能をインライン化から、コンパイラを防ぐためです。@SergeBallestaがコメントに指摘しているように、リンカーのトリックはインライン展開されていると機能しません。

    多分ハックのビットが、ちょっと、それは動作します!

    +1

    @SergeBallesta:うーん、 '-O0'で動作します。 '-O1'以上ではそれはしません。 – rodrigo

    +0

    しないでください!誤って使用されている代入演算子のためにこのエラーが発生することは絶対にわかりません。数年後、このリンカの旗は追跡が難しいバグかもしれません。 – Richard

    1

    まあ、標準ライブラリは... 標準であり、開発者がそれを微調整するためのフックを提供していないことを恐れています。

    私はと言っても過言ではありません;-))標準ライブラリヘッダーはテキストファイルなので、ローカルデベロッパー環境で簡単に変更することができます。おそらくそれほど悪くない方法は、変更されたヘッダー以外の元のヘッダーへのリンクを含むフォルダーをセットアップし、そのフォルダーをシステムヘッダーに使用するようコンパイラーに指示することです。道、あなたが欲しいものを変更することができます

    が...移植性と保守性...それは本当にデスペラードソリューションです...

    +0

    最初の文章は疑問点です。あなたの選択の任意の動的言語を取る(Javascript、Python、Ruby、...)、*スタンダードライブラリがありますが、あなたは最も奇妙な方法でそれをねじることができます。また、C++標準ライブラリは、テンプレート引数として、あるいは "オープン関数"として、 'std :: hash'と考えている)カスタマイズポイントを提供し、POSIXとWin32はマクロを使った条件付きの包含を可能にします。標準ライブラリへのカスタマイズ、言語自体(コンパイラのコンパイル時のスイッチとして、定義されるマクロとして...)にまで拡張されます。 –

    0

    これは私が何を知っていないので、特定++打ち鳴らすされます同等の機能がgnuツールチェーンで呼び出されます。それはいくぶん過度のものです。

    リンゴを使用してシンボルを交換することの提案は、インラインでない場合に最適です。時々O0ですべてを構築すれば十分です。

    それ以外の場合、llvm(clang)ツールチェーンは、最適化パイプラインに対する驚くほどの制御を提供します。たとえば、最適化せずにコンパイルした後、optを使用して最適化を実行した後、オブジェクトファイルに変換することができます。

    clang++ -c test.cpp -O0 --emit-llvm test.ll 
    opt -O3 test.bc -o faster.ll 
    clang++ -c faster.bc -o test.o 
    

    optツールは拡張可能です。私は正直言ってそれが拡張するのは簡単ではないと言うことはできませんが、プロセスは十分に文書化されています。あなたの標準ライブラリ関数が見えるときに警告するコンパイラパスを書くことができます。あなたはオプトの単一の呼び出しを使用することができます(単に有用ではありません)カスタムパスが正しい確信していた場合

    clang++ -c test.cpp -O0 --emit-llvm test.ll 
    opt --load DeprecationPass.so test.bc -o /dev/null 
    opt -O3 test.bc -o faster.ll 
    clang++ -c faster.bc -o test.o 
    

    :最終的な結果は次のように呼び出すことができます。 clangフロントエンドを介してフラグを渡すことはおそらく可能ですが、それはすぐにはわかりません。

    全体として、rodrigoの提案に従い、O0で製品全体を構築することはおそらくより良い計画ですが、clangがこのようなことを可能にすることはエキサイティングです。