首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >带有std::ostream的解密表达式(用于SFINAE)

带有std::ostream的解密表达式(用于SFINAE)
EN

Stack Overflow用户
提问于 2016-05-27 18:13:35
回答 1查看 1.8K关注 0票数 18

我正在尝试创建一个类型特征类,以确定特定类型的T是否可以通过std::ostream<<操作符进行流式传输。我正在使用一种简单的SFINAE技术。

最终,我尝试评估替换失败的表达式是:

代码语言:javascript
复制
decltype(std::declval<std::ostream>() << std::declval<T>()) ;

我的预期是,给定一个类型为T的实例t和一个std::ostream实例os,如果表达式os << t格式错误,则应该发生替换失败。

但是很明显,无论T类型是什么,这里都不会发生替换失败。即使我只是使用上面的decltype表达式声明了一个typedef,在SFINAE的上下文之外,它也可以顺利地编译,即使T不能与std::ostream一起使用。

例如:

代码语言:javascript
复制
struct Foo  { };

int main()
{
    // This compiles fine using GCC 4.9.2
    //
    typedef decltype(
        std::declval<std::ostream>() << std::declval<Foo>()
    ) foo_type;
}

上面的代码使用GCC 4.9.2可以很好地编译,这并不是我所期望的,因为使用Foo类型时<<运算符不会被重载。当然,如果我说:

代码语言:javascript
复制
std::cout << Foo();

..。我得到一个编译器错误。那么,为什么上面的decltype表达式还要编译呢?

EN

回答 1

Stack Overflow用户

发布于 2016-05-27 18:30:39

如果查看头文件ostream,就会发现因为std::declval会生成rvlaue引用,所以实际上有一个匹配的通用operator<<

代码语言:javascript
复制
#if __cplusplus >= 201103L
  /** 
   *  @brief  Generic inserter for rvalue stream
   *  @param  __os  An input stream.
   *  @param  __x  A reference to the object being inserted.
   *  @return  os  
   *   
   *  This is just a forwarding function to allow insertion to
   *  rvalue streams since they won't bind to the inserter functions
   *  that take an lvalue reference.
  */  
  template<typename _CharT, typename _Traits, typename _Tp>
    inline basic_ostream<_CharT, _Traits>&
    operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
    {   
      __os << __x;
      return __os;
    }   
#endif // C++11

这就解释了为什么没有替换失败的原因。然而,这实际上不能与std::cout << Foo()调用相匹配。以下是编译错误的相关部分:

代码语言:javascript
复制
/usr/local/bin/../lib/gcc/x86_64-pc-linux-gnu/6.1.0/../../../../include/c++/6.1.0/ostream:628:5: note: candidate function [with _CharT = char, _Traits = std::char_traits<char>, _Tp = Foo] not viable: no known conversion from 'ostream' (aka 'basic_ostream<char>') to 'basic_ostream<char, std::char_traits<char> > &&' for 1st argument
    operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
    ^

这里的问题是lhs只能是一个右值引用,但你(显然)在调用中使用了一个左值(即std::cout)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37480778

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档