C++ 仅当返回表达式有效时才启用模板

C++ 仅当返回表达式有效时才启用模板,c++,templates,sfinae,C++,Templates,Sfinae,我想用这种风格在std::ostream上编写一个包装器: #include <iostream> struct OstreamWrapper { OstreamWrapper(std::ostream &out) : out(out) {} template< typename T > decltype(auto) operator<<(T &&arg) { return out << std::m

我想用这种风格在
std::ostream
上编写一个包装器:

#include <iostream>

struct OstreamWrapper {
  OstreamWrapper(std::ostream &out) : out(out) {}

  template< typename T >
  decltype(auto) operator<<(T &&arg) {
    return out << std::move< T >(arg);
  }

  std::ostream &out;
};

int main() {
  OstreamWrapper wrap(std::cout);
  wrap << "Hello, world!";  // This works
  wrap << std::endl;        // This does not work
  return 0;
}
但这是不正确的,因为在计算模板表达式时,arg尚未定义

  template< typename T,
            typename = decltype(out << std::declval< T >()) >
  decltype(auto) operator<<(T &&arg) {
    return out << std::move< T >(arg);
  }
template

decltype(auto)操作符您可以将重载添加到强制类型(因此选择唯一的可用重载):

struct-OstreamWrapper{
显式OstreamWrapper(std::ostream&out):out(out){}
模板

decltype(auto)操作符您可以将重载添加到强制类型(因此选择唯一的可用重载):

struct-OstreamWrapper{
显式OstreamWrapper(std::ostream&out):out(out){}
模板

decltype(auto)运算符未重载。它是一个声明如下的函数模板:

template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );
模板
std::basic_ostream&endl(std::basic_ostream&os);

它直接用于
std::ostream
的原因是适当的
操作符
std::endl
没有重载。它是一个声明如下的函数模板:

template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );
模板
std::basic_ostream&endl(std::basic_ostream&os);

它直接适用于
std::ostream
的原因是,合适的
操作员很好地接住了
向前
移动
。很好地接住了
向前
移动
template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );