如何通过这个简单示例在 C++11 中正确使用可变参数模板?
How to correctly use variadic templates in C++11 with this simple example?
使用 VS2013 (VC2012)。
在阅读了很多关于可变参数模板的答案并用我自己的代码失败后,我想问一下如何 compile/achieve 我的例子,这并不代表我的全部需要,但我更喜欢按顺序排列让大家更容易、更清晰地理解我的观点。
我最好需要一个接收任意数量的 (int, const char * 元组) 的函数,并在函数内部访问此列表中的任何元组。因为我相信在通过互联网阅读后这是不可能的,所以我尝试用任意数量的 class 定义可变参数模板,其中包含 int 和 const char* 成员,但它失败了。
请注意,我想将不同文件中的声明与定义分开,这一点很重要:
phrases.h:
class CPhraseParamInfo { // Nothing, for easier example }
class CPhrases
{
template<class... T> void Test(T... paramsInfo);
}
phrases.cpp
template<CPhraseParamInfo...> void CPhrases::Test(CPhraseParamInfo... param)
{ // Nothing, for easier example }
错误(已翻译):
error C2993: 'CPhraseParamInfo' : invalid type for the template parameter '__formal' without defined type
error C3543: 'CPhraseParamInfo': doesn't contain a parameter pack
error C2244: 'CPhrases::Test' : cannot match the function definition with an existent declaration
请记住,如果可能的话,我更喜欢第一种方法。我希望我已经足够清楚了。
谢谢!
模板函数的定义必须在使用它的地方可见,除非出现异常情况。
你可以这样做:
class CPhraseParamInfo { // Nothing, for easier example }
class CPhrases {
void Test( CPhraseParamInfo* start, CPhraseParamInfo* end );
template<class... T> void Test(T... paramsInfo) {
CPhraseParamInfo buff[]={paramsInfo...};
return Test(buff, buff+sizeof...(paramsInfo));
}
};
然后在你的 cpp 文件中:
void CPhrases::Test(CPhraseParamInfo* start, CPhraseParamInfo* end)
{
// Nothing, for easier example
}
或类似的东西。
谢谢@Yakk。这是扩展示例,包含我的部分真实代码,以展示如何允许最后一个参数用作任意值传递(对于某些短语 va_args 处理),如果有人觉得它有用的话。这里的关键是使用与模板调用列表 (< CPhraseParamInfo, ... >):
相同数量的可变参数 class 来调用可变参数模板函数
phrases.h:
class CPhrases:
{
template<class... ParamInfo, typename... Arg> static void
LoadForPlayer(CHL2RP_Player *player, char *dest, int maxlen, const char *header,
const char *prependText, ParamInfo&... paramsInfo, Arg... args)
{
CPhraseParamInfo paramsInfoBuff[] = { paramsInfo... };
LoadForPlayer(player, dest, maxlen, header, prependText, paramsInfoBuff, sizeof paramsInfoBuff, args...);
}
static void LoadForPlayer(CHL2RP_Player *player, char *dest, int maxlen, const char *header, const char *prependText,
CPhraseParamInfo *paramsInfoBuff, int paramCount, ...);
static FORCEINLINE void LoadRegionChat(CHL2RP_Player *player, char *dest, int maxlen, const char *talker, const char *message)
{
LoadForPlayer<CPhraseParamInfo, CPhraseParamInfo>(player, dest, maxlen, REGION_CHAT_HEADER, INDIAN_RED_CHAT_COLOR,
CPhraseParamInfo(CPhraseParamInfo::STRING, TEAM_CHAT_COLOR "%s" DEFAULT_CHAT_COLOR), CPhraseParamInfo(CPhraseParamInfo::STRING, "%s"), talker, message);
}
}
使用 VS2013 (VC2012)。
在阅读了很多关于可变参数模板的答案并用我自己的代码失败后,我想问一下如何 compile/achieve 我的例子,这并不代表我的全部需要,但我更喜欢按顺序排列让大家更容易、更清晰地理解我的观点。
我最好需要一个接收任意数量的 (int, const char * 元组) 的函数,并在函数内部访问此列表中的任何元组。因为我相信在通过互联网阅读后这是不可能的,所以我尝试用任意数量的 class 定义可变参数模板,其中包含 int 和 const char* 成员,但它失败了。
请注意,我想将不同文件中的声明与定义分开,这一点很重要:
phrases.h:
class CPhraseParamInfo { // Nothing, for easier example }
class CPhrases
{
template<class... T> void Test(T... paramsInfo);
}
phrases.cpp
template<CPhraseParamInfo...> void CPhrases::Test(CPhraseParamInfo... param)
{ // Nothing, for easier example }
错误(已翻译):
error C2993: 'CPhraseParamInfo' : invalid type for the template parameter '__formal' without defined type
error C3543: 'CPhraseParamInfo': doesn't contain a parameter pack
error C2244: 'CPhrases::Test' : cannot match the function definition with an existent declaration
请记住,如果可能的话,我更喜欢第一种方法。我希望我已经足够清楚了。
谢谢!
模板函数的定义必须在使用它的地方可见,除非出现异常情况。
你可以这样做:
class CPhraseParamInfo { // Nothing, for easier example }
class CPhrases {
void Test( CPhraseParamInfo* start, CPhraseParamInfo* end );
template<class... T> void Test(T... paramsInfo) {
CPhraseParamInfo buff[]={paramsInfo...};
return Test(buff, buff+sizeof...(paramsInfo));
}
};
然后在你的 cpp 文件中:
void CPhrases::Test(CPhraseParamInfo* start, CPhraseParamInfo* end)
{
// Nothing, for easier example
}
或类似的东西。
谢谢@Yakk。这是扩展示例,包含我的部分真实代码,以展示如何允许最后一个参数用作任意值传递(对于某些短语 va_args 处理),如果有人觉得它有用的话。这里的关键是使用与模板调用列表 (< CPhraseParamInfo, ... >):
相同数量的可变参数 class 来调用可变参数模板函数phrases.h:
class CPhrases:
{
template<class... ParamInfo, typename... Arg> static void
LoadForPlayer(CHL2RP_Player *player, char *dest, int maxlen, const char *header,
const char *prependText, ParamInfo&... paramsInfo, Arg... args)
{
CPhraseParamInfo paramsInfoBuff[] = { paramsInfo... };
LoadForPlayer(player, dest, maxlen, header, prependText, paramsInfoBuff, sizeof paramsInfoBuff, args...);
}
static void LoadForPlayer(CHL2RP_Player *player, char *dest, int maxlen, const char *header, const char *prependText,
CPhraseParamInfo *paramsInfoBuff, int paramCount, ...);
static FORCEINLINE void LoadRegionChat(CHL2RP_Player *player, char *dest, int maxlen, const char *talker, const char *message)
{
LoadForPlayer<CPhraseParamInfo, CPhraseParamInfo>(player, dest, maxlen, REGION_CHAT_HEADER, INDIAN_RED_CHAT_COLOR,
CPhraseParamInfo(CPhraseParamInfo::STRING, TEAM_CHAT_COLOR "%s" DEFAULT_CHAT_COLOR), CPhraseParamInfo(CPhraseParamInfo::STRING, "%s"), talker, message);
}
}