提问者:小点点

stringstream和nullptr的子类


这个简单的代码可以用clang编译,但不能用g编译。里面有什么未定义的吗?(需要模板函数让clang高兴)GCC8.2.0(与-std=c 17一起使用)说运算符

#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;
}

共1个答案

匿名用户

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

您的代码导致std::的实例化__is_insertable

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 {};

如果一切顺利,您的运算符

现在由于错误51577,您的运算符

注意GCC9编译这段代码。这是因为有一个新的重载

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

…在C 17中添加,因此无论您的运算符是否__is_insertable都可以成功实例化

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

对于postfix表达式是依赖名称的函数调用,使用通常的查找规则([base. lookup.unqual]、[base.lookup.argdep])查找候选函数,但以下情况除外:

>

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

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

    您的运算符