2017-07-03 98 views
0

我指这个link实施variadic template为什么C++ variadic模板不接受iostream值作为参数?

#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

无关变量模板BTW。 – Jarod42

+2

你的理解是不正确的。按值传递涉及复制,并非所有类型都允许。 – StoryTeller

+0

@StoryTeller我不会说“不正确” - 它相当“不完整”。在一般情况下,传递值确实比较慢,因为必须调用复制构造函数(这是缺少的难题)。 –

回答

4

很简单,因为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的甲&)':试图引用已删除的功能

2

的解释是在第一对错误消息的线。

std::ostream实际上是typedef对于std::basic_ostream<char, std::char_traits<char> >

通过值传递std::ostream调用该对象的复制构造函数,并且std::basic_ostream模板已经显式删除了复制构造函数,因此无法调用该构造函数。

相关问题