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 中传递代码,这将找到每个调用您的函数的 gimple,并检查参数是否确实是一个文字字符串。融化示例的示例ex06应该会激发您的灵感。然后订阅gcc-melt@googlegroups.com并在那里询问您的 MELT 特定问题。

当然,这不是一个万无一失的方法:该函数可以通过指针间接调用,并且它可以例如具有部分文字字符串,例如f("hello world I am here"+(i%4))在概念上是带有一些文字字符串(例如在.rodata段中)的调用,但不在生成的代码中也不在gimple中。

于 2012-12-05T14:08:45.007 回答
1

我用这个:

// 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);

如果你做这样的事情:

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

你得到一个编译器错误。

于 2017-11-28T13:54:43.287 回答