// Fallback, anything with an operator() template <typename T> struct function_traits : public function_traits<decltype(&T::operator())> > { };
What does T::operator()
mean here?
This is code from pytorch.
Note that I'm the author of FunctionTraits. Are you already familiar with "function objects", AKA "functors". Probably not so Google this first if required (also see "Motti's" response). I'll proceed as if you don't have much experience with this.
In the code you posted, "T" is intended to be a functor, i.e., a class with a non-static member function "T::operator()" declared. The purpose of the "function_traits" struct being declared is to retrieve the function traits for the latter member function. IOW, given any class or struct like so:
class Whatever
{
public:
float operator()(int);
};
First note that "Whatever" is a class that declares a non-static member function called "operator()" so "Whatever" is a functor by definition (since it's a class that declares a non-static "operator()" member - its signature is irrelevant). Note that "operator()" simply allows you to invoke this member using an instance of "Whatever" as if it were a function. You can therefore do this:
Whatever whatever;
whatever(3);
And it invokes the "operator()" member. I won't get into the uses of this syntax here since there's plenty of info on the subject elsewhere. For now suffice to say that the call to "whatever(3)" simply allows you to invoke the member function called "operator()" as if "whatever" were a function by using function call syntax as seen. It's just syntactic sugar for this however:
whatever.operator()(3);
You can even call it this way, since it's no different than any other non-static member function call except the function's name is "operator()" which is a special name recognized by the compiler (known as the function call operator). It's still no different than any other member function however other than the ability to call it using function call syntax. It can therefore take any parameters you want (an "int" in the above example), or return any type ("float" in the above example), or be "const", or "noexcept", etc.
The purpose of the "function_traits" struct you posted is therefore to retrieve the function traits for this member function. IOW, if you do this for instance:
using WhateverTraits = function_traits<Whatever>;
"function_traits" is being specialized on a functor ("Whatever") so it will store the traits for member function "Whatever::operator()". It does so by simply inheriting from "function_traits<decltype(&T::operator())> which is simply the specialization of "function_traits" taking a non-static member function pointer type. The call to "decltype(&T::operator())" simply passes the type of member "T::operator()" to the latter specialization so in the above case it's passing the type of non-static member function "Whatever::operator()". To break this down further, the call to:
&Whatever::operator()
Returns a pointer to member function "Whatever::operator()" so in this case it's a pointer to a non-static member function taking an "int" parameter and returning a "float". The call to:
decltype(&Whatever::operator())
Then simply yields the type of this pointer which is:
float (Whatever::*)(int)
This type is then passed as the template arg to the "function_traits" base class. By doing so it's delegating the work of retrieving the function traits for functor "T" by inheriting from the specialization taking a member function pointer type, in this case the member function pointer type "&T::operator()" (so "&Whatever::operator()" in the above example and hence the pointer type just above). You therefore get the traits back for that member function.
It's just a quick and easy way to implement "function_traits" for functors by inheriting from the specialization for non-static-member functions.
I hope that helps.