Reputation: 14434
On my Visual Studio project I had the following and it worked fine:
template <typename T>
void function(T type)
{
std::result_of<T()>::type myVar = 5; // This compiled fine with Visual Studio,
but with GCC it shows the following errors:
//error: dependent-name ‘std::result_of<T()>::type’ is parsed as a non-type,
//but instantiation yields a type. note: say ‘typename std::result_of<T()>::type’ if a type is meant
}
int main() {
auto lambda = []() { return float(); };
function(lambda);
return 0;
}
I just want to understand, is the compiler insisting that I preface the std::result_of with "typename" because it could be ambiguous, in that std::result_of could return a class, and then ::type could be a member of that class? Is that why it's insisting that typename be added? If this is the case then why does Visual Studio allow it? Is it non compliant?
Also, because I've read that result_of is being deprecated as of C++14 or C++17, I wanted to try and use the more generic decltype, which is supposed to work in more circumstances. So I tried:
template <typename T>
void function(T type)
{
decltype(T()) myVar = 5; // Error, use of deleted function‘main()::<lambda()>::<lambda>()’ main.cpp
}
So I'm aware that a lambda has a deleted default constructor and copy assignment operator, but in this case I really think that when passing the lambda to this templated function the lambda's copy constructor is called, which it does have. Then when I do decltype(T()) I assume this would be calling its operator() function. I don't understand why it says something about deleted function.
And finally I tried with:
decltype(std::declval<T()>) myVar = 5;
Because I thought that declval can be used as if creating a fake instance of whatever call you make, at least that's how it was explained to me. This also fails with error:
"invalid initialization of reference of type ‘main()::&&’ from expression of type ‘int"
Upvotes: 2
Views: 1308
Reputation: 8511
result_of
First, the GCC compiler requires the keyword typename
before std::result_of
because the return value of the latter is a class. And you have to instruct it to use its type to declare a new variable.
Regarding your comment:
Also, because I've read that result_of is being deprecated as of C++14 or C++17
std::result_of
is deprecated as of C++17 (See here why) and is replaced by
the newly introduced std::invoke_result
, so you could use it instead if you have a compliant compiler.
decltype
Since std::result_of
is declared in terms of decltype
in the following manner:
template<typename _Signature>
struct result_of;
template<typename _Functor, typename... _ArgTypes>
struct result_of<F(Args...)> {
typedef decltype( std::declval<F>()(std::declval<Args>()...) ) type;
};
You could use a similar definition:
decltype( std::declval<T>()() ) myVar = 5;
Upvotes: 5