2012-12-05 44 views
8
私は唯一のパラメータとして文字列リテラルを受け入れるC++ 11の機能書きたい

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ではプラットフォーム固有の方法はありませんか?私は、最も近いあなたが得ようとしていると思います

+0

文字列リテラル以外ではできない文字列リテラルではどうしますか?そして、文字列リテラルを使って初期化された 'const char * const'変数を渡すのはどうですか?または 'const char(&array)[]'は文字列リテラルへの参照ですか? – hvd

+2

これは不可能です。文字列リテラルは 'char const [N]'配列なので、文字列リテラルと区別できません。 – Xeo

+0

おそらく、このrvalue参照のときにデータを読み込み専用にする型に変換するユーザー定義の文字列リテラルを使用している(名前付き変数ではない)可能性があります。目標は、文字列がコール時にコードに文字どおり入力され、アプリケーションイメージに静的にコンパイルされるようにすることです。 –

答えて

12

は、それはリテラルと配列ではなくポインタを使用してコンパイルされます。この

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

です。

+0

'std :: enable_if <>'を賢明に使って、大部分の非リテラル配列を扱うことをさらに防ぐことができるかもしれません。 enable_ifに入れるものの例については、http://stackoverflow.com/questions/14805011/how-to-detect-a-string-literal-with-type-traitsを参照してください(static_assertを使用していますが、それは同じですが概念)。 – wjl

3

GCC拡張モジュールをコンパイル時にチェックして、特定の関数がリテラル文字列でのみ呼び出されるようにすることもできます。

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

基本的には、GCCの中に新しいパスを追加し、MELTで渡すコードは、関数の呼び出しであるすべてのジンプルを見つけ、引数が実際にリテラル文字列であることを確認します。 ex06の例はmelt-examplesにあります。その後、[email protected]に登録してMELTに特定の質問をしてください。

もちろん、これは簡単な方法ではありません。ポインタを介して関数を間接的に呼び出すことができます。部分的なリテラル文字列を持つ。 f("hello world I am here"+(i%4))は、概念的には、リテラル文字列(例えば、.rodataセグメント)を含むコールですが、生成されたコードやジンプルには含まれません。

// these are used to force constant, literal strings in sqfish binding names 
// which allows to store/copy just the pointer without having to manage 
// allocations and memory copies 
struct _literalstring 
{ 
    // these functions are just for easy usage... not needed 
    // the struct can be empty 
    bool equal(_literalstring const *other) { return !strcmp((const char *)this, (const char *)other); } 
    bool equal(const char *other) { return !strcmp((const char *)this, other); } 
    const char *str(void) { return (const char *)this; } 
    bool empty(void) { return *(const char *)this == 0; } 
}; 

typedef _literalstring *LITSTR; 

constexpr LITSTR operator "" _LIT(const char *s, size_t) { 
    return (LITSTR)s; 
} 

その後、あなたはこのようにあなたの関数を宣言します:

void myFunc(LITSTR str) 
{ 
    printf("%s\n", str->str()); 
    printf("%s\n", (const char *)str); 
    const char *aVar = str->str(); 
    const char *another = (const char *)str; 
} 

そして、あなたはこのようにそれを呼び出す:あなたが何かをした場合

myFunc("some text"_LIT); 

私はこれを使用

1

このように:

myFunc("some text"); 
myFunc(aTextVariable); 

コンパイルエラーが発生します。

関連する問題