15

文字列リテラルのみをパラメーターとして受け入れる C++11 関数を作成したいと考えています。

 void f(const char* s) { static_assert(s is a string literal); ... }

あれは:

 f("foo"); // OK

 char c = ...;
 f(&c); // ERROR: Doesn't compile

 string s = ...;
 f(s.c_str()); // ERROR: Doesn't compile

 etc

これを実装する方法はありますか?関数の署名は、マクロの使用やその他の言語機能の追加と同様に、変更可能です。

これが不可能な場合、最も近い近似値はどれですか? (とにかく、ユーザー定義のリテラルは役に立ちますか?)

そうでない場合、GCC 4.7/Linux にプラットフォーム固有の方法はありますか?

4

3 に答える 3

17

あなたが得ようとしている最も近いのはこれだと思います

template<int N>
void f(const char (&str)[N]){
  ...
}

リテラルと配列ではコンパイルされますが、ポインターではコンパイルされません。

于 2012-12-05T13:34:15.617 に答える
4

別の方法として、特定の関数がリテラル文字列でのみ呼び出されることをコンパイル時にチェックする GCC 拡張機能を作成することもできます。

MELTを使用して GCC を拡張できます。MELT は、GCC コンパイラを拡張する高レベルのドメイン固有言語であり、必要な種類のチェックに非常に適しています。

基本的に、GCC 内に新しいパスを追加し、MELT を渡すコードを追加して、関数の呼び出しであるすべての gimpl を見つけ、引数が実際にリテラル文字列であることを確認します。Melt-examples の例ex06、あなたにインスピレーションを与えるはずです。次に、gcc-melt@googlegroups.comに登録して、そこで MELT に関する質問をしてください。

もちろん、これは絶対確実なアプローチではありません。関数はポインタを介して間接的に呼び出される可能性があり、たとえば部分的なリテラル文字列を持つこともできます。たとえば、f("hello world I am here"+(i%4))概念的にはリテラル文字列 (.rodataセグメント内など) を使用した呼び出しですが、生成されたコードではそうではありません。ギンプルにもありません。

于 2012-12-05T14:08:45.007 に答える