【问题标题】:subclass of stringstream and nullptrstringstream 和 nullptr 的子类
【发布时间】:2019-01-26 06:15:31
【问题描述】:

这个简单的代码可以用clang++编译,但不能用g++编译。 里面有什么未定义的吗? (需要模板功能才能让clang开心) GCC 8.2.0(与 -std=c++17 一起使用)说 operator

#include <cstddef>
#include <utility>
#include <sstream>

template<class Out>
Out&& operator<<(Out&& out, std::nullptr_t) {
  out << "nullptr";
  return std::forward<Out>(out); }

struct A : std::stringstream { };

int main() {
  A{} << nullptr;
}

【问题讨论】:

    标签: c++ templates gcc clang language-lawyer


    【解决方案1】:

    我相信这是由 GCC 的Bug 51577 引起的。

    你的代码导致std::__is_insertable&lt;std::basic_ostream&lt;char&gt;&amp;, std::nullptr_t&amp;, void&gt;在libstdc++中的实例化,那我们看看the definition of this struct

    template<typename _Ostream, typename _Tp, typename = void>
      struct __is_insertable : false_type {};
    
    template<typename _Ostream, typename _Tp>
      struct __is_insertable<_Ostream, _Tp,
                             __void_t<decltype(declval<_Ostream&>()
                                               << declval<const _Tp&>())>>
                                      : true_type {};
    

    如果一切顺利,你的operator&lt;&lt;在这里是不可见的1,那么部分特化被SFINAE禁用,__is_insertable被正常实例化为@987654332的派生类@。

    现在由于错误 51577,您的 operator&lt;&lt; 在此处可见,导致部分专业化完美匹配。但是,在实例化__is_insertable 时,您的operator&lt;&lt; 由于某种原因是不可见的,因此由于operator&lt;&lt; 的模糊过载而发生错误。


    注意 GCC 9 compiles 这段代码。这是因为有一个new overload

    basic_ostream& operator<<( std::nullptr_t );
    

    ... 在 C++17 中添加,因此无论您的 operator&lt;&lt; 是否可见,都可以成功实例化 __is_insertable。错误仍然存​​在。


    1 这是因为[temp.dep.candidate]/1:

    对于后缀表达式是从属名称的函数调用,使用通常的查找规则([basic.lookup.unqual]、[basic.lookup.argdep])找到候选函数,除了:

    • 对于使用非限定名称查找的部分查找,只能找到来自模板定义上下文的函数声明。

    • 对于使用关联命名空间 ([basic.lookup.argdep]) 的查找部分,只能找到在模板定义上下文或模板实例化上下文中找到的函数声明。

    当然,您的operator&lt;&lt; 无法从模板定义上下文中找到。参数类型为std::basic_ostream&lt;char&gt;std::nullptr_t,因此associated namespaces 不包含全局命名空间。因此,您的operator&lt;&lt; 应该找不到。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-28
      • 1970-01-01
      • 2013-06-08
      • 2018-05-27
      • 1970-01-01
      • 1970-01-01
      • 2011-01-19
      相关资源
      最近更新 更多