c++c++11compile-timedecltypeextraction-operator

Why Can't I do decltype on an Extraction Operator


It seems like this should be legal:

decltype(declval<istream>().operator>>(declval<istream>(), declval<int>())) test;

But when I try to compile I get:

error C2661: std::basic_istream<char,std::char_traits<char>>::operator >>: no overloaded function takes 2 arguments

Am I doing something wrong? Why doesn't this evaluate to an istream?

EDIT:

It has been pointed out that because istream& istream::operator>>(int&) is a method, the first value is passed automatically.

However: decltype(declval<istream>().operator>>(declval<int>())) test; errors with:

error C2664: std::basic_istream<char,std::char_traits<char>> &std::basic_istream<char,std::char_traits<char>>::operator >>(std::basic_streambuf<char,std::char_traits<char>> *): cannot convert argument 1 from std::ios_base::iostate to std::basic_istream<char,std::char_traits<char>> &(__cdecl *)(std::basic_istream<char,std::char_traits<char>> &)

And decltype(istream::operator >> (declval<istream>(), declval<int>())) test; errors with:

error C2661: std::basic_istream<char,std::char_traits<char>>::operator >>: no overloaded function takes 2 arguments


Solution

  • The operator>> that takes an int is a member function (you're currently using the syntax for both member and nonmember functions) and it takes its argument by reference (so that it can populate it - declval<int>() gives you an int&&, you need declval<int&>() to get an int&):

    using T = decltype(declval<istream>().operator>>(declval<int&>()));
    

    Even better would be to not invoke the operator directly, so you don't have to worry about which operator<< is a member and which is not:

    using T = decltype(declval<istream&>() >> declval<int&>());