可变参数模板 - 编译错误

时间:2011-08-19 01:28:11

标签: c++ c++11 variadic-templates

您可以帮助我修复以下代码中的编译错误:

#include <sstream>
#include <iostream>

using namespace std;

template<typename T, typename ...P>
class Mystrcat{
 public:
 Mystrcat(T t, P... p){init(t,p...);}

 ostringstream & get(){return o;}         

 private:
 ostringstream o;
 void init(){}
 void init(T t, P... p);
};

template<typename T, typename ...P>
void Mystrcat<T,P...>::init(T t, P ...p){
  o << t;
  if (sizeof...(p)) init(p...);
}

int main(){
 Mystrcat<char*,char *> m("Amma","Namasivayah");
 cout << m.get().str();
}

我收到错误,没有匹配函数来调用

‘Mystrcat<char*, char*>::init(char*&)’

注意:候选人是:

void Mystrcat<T, P>::init() [with T = char*, P = char*]
void Mystrcat<T, P>::init(T, P ...) [with T = char*, P = char*]

gcc版本4.4.3(Ubuntu 4.4.3-4ubuntu5)

由于 苏雷什

1 个答案:

答案 0 :(得分:0)

您收到此错误是因为无法将p解压缩到init函数中。在您的实例化Mystrcat<char*, char *>中,解压缩P...将在类型中生成一个单独的内容:char*,其中没有带有该签名的init(实例化版本将有一个void init()void init(char*, char*),而您正试图致电init(char*))。

事实上,您的模板无法实例化,因为init总是会比您在void Mystrcat<T,P...>::init(T t, P ...p)中提供的参数多一个。如果更改定义以调用已定义的内容:

template<typename T, typename ...P>
void Mystrcat<T,P...>::init(T t, P ...p){
  o << t;
  if (sizeof...(p)) init(t, p...);
}

然后这将起作用(至少在g ++ - 4.5.2中)。


编辑:我认为这正是您真正想要的:

#include <sstream>
#include <iostream>

class MyCollector
{
public:
    template <typename... T>
    explicit MyCollector(const T&... args)
    {
        init(args...);
    }

    std::string str()
    {
        return _stream.str();
    }

private:
    void init()
    { }

    template <typename First, typename... Rest>
    void init(const First& first, const Rest&... rest)
    {
        _stream << first;
        init(rest...);
    }

    std::ostringstream _stream;
};

int main()
{
    MyCollector collector("Whatever ", "stuff like ", 2, " or ", 3.14, "\n");
    std::cout << collector.str();
    return 0;
}