Ant*_*ile 5 c++ templates iostream manipulators
我不确定这段代码是否会编译.
我正在使用的示例代码:
#include <iostream>
using std::cout;
using std::endl;
class Foo {
public:
template<typename T>
Foo& operator<<(const T& t) {
cout << t;
return *this;
}
};
int main() {
Foo foo;
foo << "Hello World"; // perfectly fine
foo << endl; // shit hits the fan
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是错误:
test.cpp:19:12: error: no match for ‘operator<<’ in ‘foo << std::endl’
test.cpp:19:12: note: candidates are:
test.cpp:10:14: note: template<class T> Foo& Foo::operator<<(const T&)
test.cpp:10:14: note: template argument deduction/substitution failed:
test.cpp:19:12: note: couldn't deduce template parameter ‘T’
Run Code Online (Sandbox Code Playgroud)
我很困惑为什么它不能替换endl(ostream& (*)(ostream&))的函数类型,T当你指定它时它显然是好的cout << endl;
我发现另外令人费解的是,这解决了问题[编辑]
Foo& operator<<(ostream& (*f)(ostream&)) {
cout << f;
return *this;
}
Run Code Online (Sandbox Code Playgroud)
如果问题不明确,我问为什么它不能首先推断出模板.
endl是一个操纵器,即它是一个未解析的函数类型。有几种重载,类型推导无法决定你想要哪一种。
更具体地说,如下所示endl(在 GNU libc++ 中):
/**
* @brief Write a newline and flush the stream.
*
* This manipulator is often mistakenly used when a simple newline is
* desired, leading to poor buffering performance. See
* http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt11ch25s02.html
* for more on this subject.
*/
template<typename _CharT, typename _Traits>
inline basic_ostream<_CharT, _Traits>&
endl(basic_ostream<_CharT, _Traits>& __os)
{ return flush(__os.put(__os.widen('\n'))); }
Run Code Online (Sandbox Code Playgroud)
更新所以,问题是,编译器无法推断出您将传递哪个实例(这是一个未解决的重载)。endl您可以通过执行 a 来解决此问题static_cast<ostream&(*)(ostream&)>(endl)。
当然,这不太方便。这是一个简单的修复:http://liveworkspace.org/code/2F2VHe$1
#include <iostream>
using std::cout;
using std::endl;
class Foo : public std::ostream
{
public:
template<typename T>
Foo& operator<<(T&& t) {
cout << std::forward<T>(t);
return *this;
}
typedef std::ostream& (manip)(std::ostream&);
Foo& operator<<(manip& m) {
cout << m;
return *this;
}
};
int main() {
Foo foo;
foo << "Hello World"; // perfectly fine
foo << endl; // everything is fine
return 0;
}
Run Code Online (Sandbox Code Playgroud)