3

Just encountered this bit of code:

if(iElement->getData().contains("someText") and iElement->getData()("someOtherText").toString() == "true")

What is boggling my mind is this part:

iElement->getData()("someOtherText").toString()

More precisely having: ()()

I haven't seen an overloader anywhere.

This is supposed to be C++ code by the way. Compiles and runs fine.

Could not find any information anywhere since I don't know what to even search for... Can someone please explain?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
solarflare
  • 423
  • 3
  • 14
  • I think the function call operator is being invoked on the object being returned by `iElement->getData()`, e.g., https://stackoverflow.com/questions/4689430/function-call-operator?noredirect=1&lq=1 – Venkatesh-Prasad Ranganath Mar 09 '20 at 23:28
  • 4
    @MarekR as M.M has pointed out (comment now deleted), this is valid c++ code. https://en.cppreference.com/w/cpp/language/operator_alternative – Sebastian Hoffmann Mar 09 '20 at 23:50
  • Your title is a bit misleading. Brackets refers to the `[]` and they are not really involved in your question. – super Mar 10 '20 at 00:09
  • @super Nomenclature regarding brackets/braces/parentheses varies by region, so I wouldn't call this misleading. They did clarify that they mean `()`. – alter_igel Mar 10 '20 at 00:25
  • @super those are square brackets :) – solarflare Mar 10 '20 at 00:32

2 Answers2

9
 iElement->getData()("someOtherText").toString()

Is processed in following order

  1. Call iElement->getData()

  2. On the object returned by getData(), call operator(), i.e the overloaded call operator, with the argument "someOtherText"

  3. On the object returned by operator(), call toString()

Notice that operator() must not necessarily be overriden. getData() could e.g return a function pointer as well.

Sebastian Hoffmann
  • 2,815
  • 1
  • 12
  • 22
  • There's also a potential call of `operator->` on `iElement`, depending on what type it is. – 1201ProgramAlarm Mar 09 '20 at 23:34
  • *'On the result call `operator()` with argument "someOtherText", i.e the overloaded call operator'* seems to suggest you're invoking a user-defined operator, which is not necessarily the case. – Aykhan Hagverdili Mar 09 '20 at 23:34
0

In question about ()() first pair of parentheses corresponds to the call iElement->getData() returning callable object and second pair of parentheses represents operator() to call returned callable object with string parameter and returning type String (which has member function toString() as in source code for String in the source code below).
For our case we declare:

function<String (string)> callableObject;

This callable object is called as

callableObject(“callOperator or functionPointer or someOtherText”);

Callable object could be constructed using call operator or function pointer (Sebastian Hoffmann and in the discussion) and other constructs (see source code for getDataWithCallableObject()):

         1 Function object
         1.1 Function object
               CallOperatorStruct callOperatorStruct;
               callableObject = callOperatorStruct;
         1.2 Lambda, named lambda
               String str;
               callableObject = [](string s) { return str; };
               auto namedLambda = [](string s) { return str; };
               callableObject = namedLambda;
         2 Function
         2.1 Free function
               callableObject = freeFunction;
         2.2 Free function pointer
               callableObject = &freeFunction;
         2.3 Member function
               callableObject = MemberFunctionStruct::staticMemberFunction;
         2.4 Member function pointer
               MemberFunctionStruct memberFunctionStruct;
               callableObject = bind (&MemberFunctionStruct::memberFunction, memberFunctionStruct, _1);
               callableObject = &MemberFunctionStruct::staticMemberFunction;

Source code

#include <functional>
#include <string>

using namespace std;
using namespace std::placeholders;

struct String {
  bool toString () {
    return "true";
  }
};

struct CallOperatorStruct {
  String operator()(string s) {
    return str;
  }

  String str;
};

struct Element {
  CallOperatorStruct& getData () {
    return data;
  }
  CallOperatorStruct data;

  static function<String (string)> getDataWithCallableObject ();
};

int main () {
  Element* iElement = new Element ();

  if (iElement->getData()("someOtherText").toString()){};

  if (iElement->getDataWithCallableObject()("someOtherText").toString()){};
}

String str;

struct MemberFunctionStruct {
  String memberFunction (string s) {
    return str;
  };

  static String staticMemberFunction(string s) {
    return str;
  };
};

String freeFunction (string s) {
  return str;
};

function<String (string)> Element::getDataWithCallableObject () {
  function<String (string)> callableObject;

  // 1 Function object
  // 1.1 Function object
  CallOperatorStruct callOperatorStruct;
  callableObject = callOperatorStruct;

  // 1.2 Lambda, named lambda
  callableObject = [](string s) { return str; };
  auto namedLambda = [](string s) { return str; };
  callableObject = namedLambda;

  // 2 Function
  // 2.1 Free function
  callableObject = freeFunction;

  // 2.2 Free function pointer
  callableObject = &freeFunction;

  // 2.3 Member function
  callableObject = MemberFunctionStruct::staticMemberFunction;

  // 2.4 Member function pointer
  MemberFunctionStruct memberFunctionObj;
  callableObject = bind (&MemberFunctionStruct::memberFunction, memberFunctionObj, _1);
  callableObject = &MemberFunctionStruct::staticMemberFunction;

  return callableObject;
}
Val
  • 211
  • 2
  • 4