2017-07-03 95 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模板已經顯式刪除了複製構造函數,因此無法調用該構造函數。

相關問題