C++ 文本中静态std::string对象的宏

C++ 文本中静态std::string对象的宏,c++,macros,c-preprocessor,stdstring,string-literals,C++,Macros,C Preprocessor,Stdstring,String Literals,假设我需要调用一个函数foo,该函数从代码中的大量位置获取常量std::string引用: int foo(const std::string&); .. foo("bar"); .. foo("baz"); 用这样的字符串文本调用函数将创建临时std::string对象,每次都复制该文本 除非我弄错了,否则编译器不会通过为每个文本创建一个静态std::string对象来优化它,该对象可以在后续调用中重用。我知道g++有高级的字符串池机制,但我认为它不会扩展到std::string对象

假设我需要调用一个函数
foo
,该函数从代码中的大量位置获取常量
std::string
引用:

int foo(const std::string&);
..
foo("bar");
..
foo("baz");
用这样的字符串文本调用函数将创建临时
std::string
对象,每次都复制该文本

除非我弄错了,否则编译器不会通过为每个文本创建一个静态
std::string
对象来优化它,该对象可以在后续调用中重用。我知道g++有高级的字符串池机制,但我认为它不会扩展到
std::string
对象本身

我可以自己进行“优化”,这会使代码的可读性降低:

static std::string bar_string("bar");
foo(bar_string);
..
static std::string baz_string("baz");
foo(baz_string);
使用Callgrind,我可以确认这确实加快了我的程序

我想我会尝试为这个制作一个宏,但我不知道这是否可能。我想要的是:

foo(STATIC_STRING("bar"));
..
foo(STATIC_STRING("baz"));
我尝试创建一个以文本作为模板参数的模板,但事实证明这是不可能的。由于在代码块中定义函数是不可能的,我完全没有主意了


有没有一种优雅的方法可以做到这一点,或者我必须求助于可读性较差的解决方案?

如果该函数
foo
没有复制字符串,那么它的接口是次优的。最好将其更改为接受
char const*
或,这样调用方就不需要构造
std::string

或添加重载:

void foo(char const* str, size_t str_len); // Does real work.

inline void foo(std::string const& s) { foo(s.data(), s.size()); }
inline void foo(char const* s) { foo(s, strlen(s)); }

您可以使用从
const char*
std::string
。我不确定细节,可能是到处使用
flyweight
就足够了。

您可以使用类似的东西创建
静态std::string
“就地”:

#包括
#包括
//字符序列
模板结构字符序列
{
使用push_back=char_序列的模板;
};
//从“\0”的字符\u序列中删除所有字符
模板结构条带序列;
模板
结构条带序列
{
使用type=char\u序列;
};
模板
结构条带序列
{
使用type=char\u序列;
};
模板
结构条带序列
{
使用type=typename strip\u sequence::type;
};
//结构来创建std::string
模板结构静态字符串;
模板
结构静态字符串
{
静态常量std::string str;
};
模板
常数
std::string static_string::str={Cs…};
//获取第i个字符的帮助程序(`0`表示越界)
模板
constexpr char at(const char(&a)[N]){返回I静态断言(N这将适用于简单字符串-不带空格:

#define DECL_STR(s) const std::string str_##s (#s)
标题中的用法(解析一次!):

代码:

func(str_Foo);
func(str_Bar);

如果您可以使用boost 1.55或更高版本,您可以

#include <boost/utility/string_ref.hpp>

void foo(const boost::string_ref& xyz)
{
}
#包括
void foo(const boost::string_ref&xyz)
{
}

如果
foo
复制了字符串,则接口是次优的。如果
foo
复制了字符串,则最好按值传递。我同意。接口不应该不必要地要求
std::string
,但有时接口不是您可以更改的,或者字符串对象实际上需要进一步更改
foo
@LuchianGrigore中的行为True。对于计数的gcc引用
std::string
,在数据副本方面,通过引用const接受它与通过值接受它一样好。我看不出这有什么帮助。如果函数
foo
使用
std::string
成员函数,例如
find
?@Rapptz,它等于帮助分配内存和复制字符串只是为了能够调用
std::string::find
,不是吗?总有一个库可以将字符串算法与字符串表示分离。std::string
的臃肿和单一接口。太棒了!唯一的缺点是它使用了一些不可用的C++11语法例如,在g++4.4.4中,使用4.8它工作得非常好。好吧,这并不是比我的“可读性较差”的解决方案更可读或更紧凑。那么,std::string const和{std::string const(“bar”);return s;}()?使用c++14,您可以使用用户定义的文本
“bar”s
,但我不确定它是否可以复制
func(str_Foo);
func(str_Bar);
#include <boost/utility/string_ref.hpp>

void foo(const boost::string_ref& xyz)
{
}