如何通过这个简单的例子在C++ 11中正确使用可变参数模板?

问题描述:

使用VS2013(VC2012)。如何通过这个简单的例子在C++ 11中正确使用可变参数模板?

在阅读了许多关于可变参数模板的答案并且没有用我自己的代码之后,我想问一下如何编译/实现我的例子,它并不代表我的全部需要,但是我希望为了使它更容易,更清洁,让大家理解我的观点。

我最好需要一个接收任意数量的(int,const char *元组)的函数,并从函数内部的这个列表中访问任何元组。由于我相信通过互联网阅读这是不可能的,我试图用任意数量的某个类来定义可变参数模板,该类将包含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 
} 

或类似的东西。

+1

这也是值得注意到VS 2012实际上并不支持可变模板。它有一个解决方法来模拟标准库的这种行为,但在VS 2013或更高版本之前,可变参数模板并不真正受支持。 –

+0

@ChuckWalbourn,对不起,我在第一行有一个错字,改为VC2012(参考VS2013自然的工具集)。 –

+0

@Yakk感谢您的解决方案,我可以完美地理解它并帮助我学习更多。现在,我正在忙着让我的代码在应答之前工作。我还需要另一个要求,认为它不会与模板发生冲突,但它仍然是我解决它的:具有va_arg解析(...)的最后一个常规可变参数。编译器会对传递给variadic paramsInfo的参数的限制感到困惑。所以我在这里把它解决了。 –

谢谢@Yakk。这里展示了一部分我的真实代码,以展示如何让最后一个参数作为arbritrary值传递(对于某些短语va_args处理),如果有人认为它有用。这里的关键是要调用可变参数模板函数模板通话清单(< CPhraseParamInfo,...>)上使用相同的量可变参数类:

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