为什么C ++ variadic模板不接受iostream值作为参数?

时间:2017-07-03 10:15:18

标签: c++

我引用此link来实施variadic template

#include <iostream>
#include <sstream>

// base case
void doPrint(std::ostream &out) {}

template <typename T, typename... Args>
void doPrint(std::ostream &out, T t, Args... args)
{
    out << t;                // add comma here, see below
    doPrint(out, args...);
}

int main() {
    // See how it works even better than varargs?
   doPrint(std::cout, "Hola", " mundo ");
   return 0;
}

但如果我从参考

更改功能参数
void doPrint(std::ostream &out)
......
template <typename T, typename... Args>
void doPrint(std::ostream &out, T t, Args... args)

值:

void doPrint(std::ostream out)
......
template <typename T, typename... Args>
void doPrint(std::ostream out, T t, Args... args)

我收到以下构建错误:

test.cpp: In function 'int main()':
test.cpp:16:40: error: 'std::basic_ostream<_CharT, _Traits>::basic_ostream(const std::basic_ostream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]' is protected within this context
    doPrint(std::cout, "Hola", " mundo ");
                                        ^
In file included from /usr/include/c++/7.1.1/iostream:39:0,
                 from test.cpp:1:
/usr/include/c++/7.1.1/ostream:391:7: note: declared protected here
       basic_ostream(const basic_ostream&) = delete;
       ^~~~~~~~~~~~~
test.cpp:16:40: error: use of deleted function 'std::basic_ostream<_CharT, _Traits>::basic_ostream(const std::basic_ostream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]'
    doPrint(std::cout, "Hola", " mundo ");
                                        ^
In file included from /usr/include/c++/7.1.1/iostream:39:0,
                 from test.cpp:1:
/usr/include/c++/7.1.1/ostream:391:7: note: declared here
       basic_ostream(const basic_ostream&) = delete;
       ^~~~~~~~~~~~~
test.cpp:8:6: note:   initializing argument 1 of 'void doPrint(std::ostream, T, Args ...) [with T = const char*; Args = {const char*}; std::ostream = std::basic_ostream<char>]'
 void doPrint(std::ostream out, T t, Args... args)
      ^~~~~~~
test.cpp: In instantiation of 'void doPrint(std::ostream, T, Args ...) [with T = const char*; Args = {const char*}; std::ostream = std::basic_ostream<char>]':
test.cpp:16:40:   required from here
test.cpp:11:12: error: 'std::basic_ostream<_CharT, _Traits>::basic_ostream(const std::basic_ostream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]' is protected within this context
     doPrint(out, args...);
     ~~~~~~~^~~~~~~~~~~~~~
In file included from /usr/include/c++/7.1.1/iostream:39:0,
                 from test.cpp:1:
/usr/include/c++/7.1.1/ostream:391:7: note: declared protected here
       basic_ostream(const basic_ostream&) = delete;
       ^~~~~~~~~~~~~
test.cpp:11:12: error: use of deleted function 'std::basic_ostream<_CharT, _Traits>::basic_ostream(const std::basic_ostream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]'
     doPrint(out, args...);
     ~~~~~~~^~~~~~~~~~~~~~
In file included from /usr/include/c++/7.1.1/iostream:39:0,
                 from test.cpp:1:
/usr/include/c++/7.1.1/ostream:391:7: note: declared here
       basic_ostream(const basic_ostream&) = delete;
       ^~~~~~~~~~~~~
test.cpp:8:6: note:   initializing argument 1 of 'void doPrint(std::ostream, T, Args ...) [with T = const char*; Args = {}; std::ostream = std::basic_ostream<char>]'
 void doPrint(std::ostream out, T t, Args... args)
      ^~~~~~~

根据我的理解,使用值可能没有良好的性能作为参考,但它不应该导致编译错误。为什么C ++ variadic模板不接受iostream值作为参数?

2 个答案:

答案 0 :(得分:5)

这很简单,因为std::basic_ostream中的复制构造函数被删除(按标准) 阅读此here at cppreference

所以std::cout你可以移动或参考

示例:

class A {
public:
    A(const A& a) = delete;
};

void foo1(const A& a)
{
    std::cout << "HEY1" << std::endl;
}
void foo2(const A a)
{
    std::cout << "HEY2" << std::endl;
}
int main() {
    A a{};
    foo1(a);
//  foo2(a);
    return 0;
}

因此,在示例中,您会看到第一个函数在删除复制构造函数时工作正常,但如果取消注释foo2(a),则可以从编译中获取一些信息,例如: (VS)

  

'A :: A(const A&amp;)':尝试引用已删除的函数

答案 1 :(得分:2)

解释是在前几行错误消息中。

std::ostream实际上是typedef的{​​{1}}。

按值传递std::basic_ostream<char, std::char_traits<char> >会调用对象的复制构造函数,std::ostream模板已明确删除了复制构造函数,因此无法调用它。