C++ gcc是否支持宏定义中的多行原始字符串文字?

C++ gcc是否支持宏定义中的多行原始字符串文字?,c++,c++11,gcc,g++,C++,C++11,Gcc,G++,我想在头文件中放入一个常量json字符串,以便其他来源可以使用和查看它。我想在C++11中使用原始字符串文字,因为它看起来清晰而漂亮。但是,我尝试了GCC4.8.5/GCC4.9.2,使用gcc-std=c++11 test.cpp编译以下代码: #包括 /*工作正常,但看起来很丑*/ #定义stru_a\ “{\n\ \“AAA\”:“a\”,\n\ \“BBB\”:\“b\”\n\ }" /*适用于VS2017,不适用于gcc*/ #定义stru_b\ R“({ “AAA”:“a”, “BB

我想在头文件中放入一个常量json字符串,以便其他来源可以使用和查看它。我想在C++11中使用原始字符串文字,因为它看起来清晰而漂亮。但是,我尝试了GCC4.8.5/GCC4.9.2,使用
gcc-std=c++11 test.cpp编译以下代码:

#包括
/*工作正常,但看起来很丑*/
#定义stru_a\
“{\n\
\“AAA\”:“a\”,\n\
\“BBB\”:\“b\”\n\
}"
/*适用于VS2017,不适用于gcc*/
#定义stru_b\
R“({
“AAA”:“a”,
“BBB”:“b”
})";
/*可以工作,但必须在头文件中使用'extern const'/'static'*/
常量字符*STR_var=1+R“(
{
“AAA”:“a”,
“BBB”:“b”
})";
int main()
{
const char*s=STR_b;
printf(“%s\n”,s);
返回0;
}
但是,我遇到编译错误:

test.cpp:16:1: error: unterminated raw string R"({ ^ test.cpp:19:3: warning: missing terminating " character })"; ^ test.cpp:19:1: error: missing terminating " character })"; ^ test.cpp:29:2: error: stray ‘R’ in program 但它显示了错误的字符串:

{ \ "AAA": "a", \ "BBB": "b" \ } { \ “AAA”:“a”\ “BBB”:“b”\ } 它是实现定义的特性吗?gcc的更高版本是否支持此功能


编辑:


我下载并编译了GCC7.3.1源代码,然后再次尝试测试代码;但是,gcc7.3.1报告的错误与GCC4.X相同。我放弃了,决定继续使用
static const char*
。@lyang的回答也很好,它打开了我的心扉。

最新更新4/4/2019

我最近听说并认为它可能是比m4更好的解决方案。它使用python进行预处理,使代码更易于阅读,如下所示(很容易支持字符串中的引号):


也许您可以将m4文件命名为
.m4
扩展名,并使用m4生成外观难看的头文件。

最新更新4/4/2019

我最近听说并认为它可能是比m4更好的解决方案。它使用python进行预处理,使代码更易于阅读,如下所示(很容易支持字符串中的引号):



也许用C++代码命名M4文件.M4扩展,并使用M4生成丑陋的头文件。< /P>原始字符串是C++编译器的一个特性,预处理器(可能)不适用于此。然而,我发现不同的预处理器之间有一些细微的差别,所以你可能会找到一个可以让你这么做的,但它肯定不是标准的。你展示的“丑陋”方式是唯一安全的方式。在这里使用

static const char*
变量有什么问题吗?@Frank是的,到目前为止,我在头文件中使用了
static const char*
变量,但我更喜欢原始字符串。如果新版本的gcc支持此功能,我将升级gcc,然后立即替换部分代码。@TaoSfqh这是一个问题。您可以将原始字符串分配给
静态常量字符*
。现在,如果你指的是字符串文字,那么你就被误导了。重复相同的文字将导致相同的结果,只是编译器需要做更多的工作。@Frank很抱歉我的表达式不清楚
static
使包含此头文件的任何源文件都有此变量的一个副本,我尝试避免此缺陷。如果我使用C++代码>外部const char */CODE >,我必须把常量字符串放在一个源中,但我希望人们可以在头文件中看到它。然而,我发现不同的预处理器之间有一些细微的差别,所以你可能会找到一个可以让你这么做的,但它肯定不是标准的。你展示的“丑陋”方式是唯一安全的方式。在这里使用
static const char*
变量有什么问题吗?@Frank是的,到目前为止,我在头文件中使用了
static const char*
变量,但我更喜欢原始字符串。如果新版本的gcc支持此功能,我将升级gcc,然后立即替换部分代码。@TaoSfqh这是一个问题。您可以将原始字符串分配给
静态常量字符*
。现在,如果你指的是字符串文字,那么你就被误导了。重复相同的文字将导致相同的结果,只是编译器需要做更多的工作。@Frank很抱歉我的表达式不清楚
static
使包含此头文件的任何源文件都有此变量的一个副本,我尝试避免此缺陷。如果我改用
extern const char*
,我必须将常量字符串放入一个源代码中,但我希望人们可以在头文件中看到它。谢谢,这对我来说是另一种新方法。但是,它需要makefiles为m4做更多的工作,而且包括此头文件在内的所有源文件(可能其他人在我的库中使用此头文件)也必须做这项工作。我进行了测试,但m4抛出了一条警告:
忽略内置m4的多余参数,并打印了错误的结果。此外,我的测试代码只是一个简单的json字符串,实际上json可能很复杂,例如,一个字段可能再次包含换行符和转义字符:
“CCC”:“c\“c\nc”
@TaoSfqh不确定为什么会显示警告,但对于更复杂的json字符串,还需要转义反斜杠,即
m4_patsubst($1,`\',`\\\'))
。考虑到您对分发的关注,我想您可以使用一些提交钩子处理所有
.m4
文件,这样最终用户只会看到带有“丑陋”的版本“宏。@TaoSfqh实际上,我不得不承认,使用m4进行此操作非常棘手,而且很难调试,特别是如果您想正确地替换换行符和反斜杠。我还想不出一个正确的方法来做这件事。抱歉。@TaoSfqh我想您可能对使用一个名为cog的python程序进行的最新更新感兴趣。谢谢,这对我来说是另一种新方法。但是,它需要makefiles为m4做更多的工作,而且包括此头文件在内的所有源文件(可能其他人在我的库中使用此头文件)也必须做这项工作。我进行了测试,但m4抛出了一条警告:
忽略内置m4的多余参数,并打印了错误的结果。另外,我的考试公司
#include <cstdio>

/*[[[cog
import cog, re

def escape_raw(s):
    s = re.sub(r'\\', r'\\\\', s) # escape backslash first
    s = re.sub(r'"', r'\"', s) # escape quotes
    return re.sub(r'\n', r'\\n\n', s) # escape newline last

def cog_define(name, val):
    cog.outl("#define {name} {val}".format(name=name, val=val))

STR_test = r"""{
    "AAA": "a",
    "BBB": "b",
    "contain \" quote": "c"
}"""

cog_define("STR_test", escape_raw(STR_test))

]]]*/
//[[[end]]]

int main()
{
    const char *s = STR_test;
    printf("%s\n", s);
    return 0;
}
#include <cstdio>

/*[[[cog
import cog, re

def escape_raw(s):
    s = re.sub(r'\\', r'\\\\', s) # escape backslash first
    s = re.sub(r'"', r'\"', s) # escape quotes
    return re.sub(r'\n', r'\\n\n', s) # escape newline last

def cog_define(name, val):
    cog.outl("#define {name} {val}".format(name=name, val=val))

STR_test = r"""{
    "AAA": "a",
    "BBB": "b",
    "contain \" quote": "c"
}"""

cog_define("STR_test", escape_raw(STR_test))

]]]*/
#define STR_test {\n
    \"AAA\": \"a\",\n
    \"BBB\": \"b\",\n
    \"contain \\\" quote\": \"c\"\n
}
//[[[end]]]

int main()
{
    const char *s = STR_test;
    printf("%s\n", s);
    return 0;
}
#include <cstdio>

m4_changecom(`/*', `*/')
m4_define(`ESCAPE_RAW', `"m4_patsubst(`m4_patsubst($1, `"', `\\"')', `
', `\\n\\
')'") /* substitute newline and double quote with escaped version */

#define STR_test ESCAPE_RAW(`{
    "AAA": "a",
    "BBB": "b"
}')

int main()
{
    const char *s = STR_test;
    printf("%s\n", s);
    return 0;
}
#include <cstdio>




#define STR_test "{\n\
    \"AAA\": \"a\",\n\
    \"BBB\": \"b\"\n\
}"

int main()
{
    const char *s = STR_test;
    printf("%s\n", s);
    return 0;
}