无法将右值引用函数与 GCC 匹配
Cannot match rvalue reference function with GCC
尝试使用右值引用时,我从 GCC 收到错误(clang 不会生成错误)。
为什么编译器会产生错误?这是 GCC 中的错误吗?
"simplified" 错误是:
|In file included from /usr/include/c++/8/sstream:38,
| from .code.tio.cpp:1:
|/usr/include/c++/8/istream: In instantiation of 'struct std::__is_extractable<std::istream&, std::istream& (*&)(std::istream&, std::string&), void>':
|/usr/include/c++/8/type_traits:131:12: required from 'struct std::__and_<std::__is_convertible_to_basic_istream<std::istringstream > >, std::__is_extractable<std::istream&, std::istream& (*&)(std::istream&, std::string&), void> >'
|/usr/include/c++/8/type_traits:136:12: required from 'struct std::__and_<std::__not_<std::is_lvalue_reference<std::istringstream > > >, std::__is_convertible_to_basic_istream<std::istringstream > >, std::__is_extractable<std::istream&, std::istream& (*&)(std::istream&, std::string&), void> >'
|/usr/include/c++/8/istream:980:5: required by substitution of 'template<class _Istream, class _Tp> typename std::enable_if<std::__and_<std::__not_<std::is_lvalue_reference<_Tp> >, std::__is_convertible_to_basic_istream<_Istream>, std::__is_extractable<typename std::__is_convertible_to_basic_istream<_Tp>::__istream_type, _Tp&&, void> >::value, typename std::__is_convertible_to_basic_istream<_Tp>::__istream_type>::type std::operator>>(_Istream&&, _Tp&&) [with _Istream = std::istringstream; _Tp = std::istream& (*&)(std::istream&, std::string&)]'
|.code.tio.cpp:12:32: required from here
|/usr/include/c++/8/istream:951:12: error: no match for 'operator>>' (operand types are 'std::istream' and 'std::istream& (*)(std::istream&, std::string&)')
| __void_t<decltype(declval<_Istream&>()
| ~~~~~~~~~~~~~~~~~~~~
| >> declval<_Tp>())>>
| ^~~~~~~~~~~~~~~~~
我要编译的代码是:
typedef std::istream &getline_type(std::istream &, std::string &);
void operator>>(std::istream &, getline_type) {} // 1
void operator>>(std::istream &&, getline_type) {}
int main()
{
std::string s;
getline_type *getline = std::getline; // 2
//using std::getline; // 3
std::istringstream("a") >> getline;
}
如果我注释掉标记为 // 1
的行,它会起作用。如果我使用标记为 // 3
的行而不是 // 2
,它也有效。
我相信 clang 正确地评估了代码的格式是否正确,但如果有正当理由拒绝代码,则可能表明 clang 中存在错误。
这似乎是一个 GCC 错误:重载决议失败的 line 是特征的 部分特化 声明的一部分,所以替换失败应该只会产生消除“过载”(偏特化)的通常效果,从而为特征产生 false_type
。然后 operator>>
模板专业化本身会出于同样的原因被消除,留下你的重载。我假设 GCC 让你的函数 bleed 进入查找集(但只是部分的,因为它最终会拒绝 istream&
过载)。
尝试使用右值引用时,我从 GCC 收到错误(clang 不会生成错误)。
为什么编译器会产生错误?这是 GCC 中的错误吗?
"simplified" 错误是:
|In file included from /usr/include/c++/8/sstream:38,
| from .code.tio.cpp:1:
|/usr/include/c++/8/istream: In instantiation of 'struct std::__is_extractable<std::istream&, std::istream& (*&)(std::istream&, std::string&), void>':
|/usr/include/c++/8/type_traits:131:12: required from 'struct std::__and_<std::__is_convertible_to_basic_istream<std::istringstream > >, std::__is_extractable<std::istream&, std::istream& (*&)(std::istream&, std::string&), void> >'
|/usr/include/c++/8/type_traits:136:12: required from 'struct std::__and_<std::__not_<std::is_lvalue_reference<std::istringstream > > >, std::__is_convertible_to_basic_istream<std::istringstream > >, std::__is_extractable<std::istream&, std::istream& (*&)(std::istream&, std::string&), void> >'
|/usr/include/c++/8/istream:980:5: required by substitution of 'template<class _Istream, class _Tp> typename std::enable_if<std::__and_<std::__not_<std::is_lvalue_reference<_Tp> >, std::__is_convertible_to_basic_istream<_Istream>, std::__is_extractable<typename std::__is_convertible_to_basic_istream<_Tp>::__istream_type, _Tp&&, void> >::value, typename std::__is_convertible_to_basic_istream<_Tp>::__istream_type>::type std::operator>>(_Istream&&, _Tp&&) [with _Istream = std::istringstream; _Tp = std::istream& (*&)(std::istream&, std::string&)]'
|.code.tio.cpp:12:32: required from here
|/usr/include/c++/8/istream:951:12: error: no match for 'operator>>' (operand types are 'std::istream' and 'std::istream& (*)(std::istream&, std::string&)')
| __void_t<decltype(declval<_Istream&>()
| ~~~~~~~~~~~~~~~~~~~~
| >> declval<_Tp>())>>
| ^~~~~~~~~~~~~~~~~
我要编译的代码是:
typedef std::istream &getline_type(std::istream &, std::string &);
void operator>>(std::istream &, getline_type) {} // 1
void operator>>(std::istream &&, getline_type) {}
int main()
{
std::string s;
getline_type *getline = std::getline; // 2
//using std::getline; // 3
std::istringstream("a") >> getline;
}
如果我注释掉标记为 // 1
的行,它会起作用。如果我使用标记为 // 3
的行而不是 // 2
,它也有效。
我相信 clang 正确地评估了代码的格式是否正确,但如果有正当理由拒绝代码,则可能表明 clang 中存在错误。
这似乎是一个 GCC 错误:重载决议失败的 line 是特征的 部分特化 声明的一部分,所以替换失败应该只会产生消除“过载”(偏特化)的通常效果,从而为特征产生 false_type
。然后 operator>>
模板专业化本身会出于同样的原因被消除,留下你的重载。我假设 GCC 让你的函数 bleed 进入查找集(但只是部分的,因为它最终会拒绝 istream&
过载)。