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?

5
  • I think the function call operator is being invoked on the object being returned by iElement->getData(), e.g., stackoverflow.com/questions/4689430/… Commented Mar 9, 2020 at 23:28
  • 4
    @MarekR as M.M has pointed out (comment now deleted), this is valid c++ code. en.cppreference.com/w/cpp/language/operator_alternative Commented Mar 9, 2020 at 23:50
  • Your title is a bit misleading. Brackets refers to the [] and they are not really involved in your question.
    – super
    Commented Mar 10, 2020 at 0: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
    Commented Mar 10, 2020 at 0:25
  • @super those are square brackets :)
    – solarflare
    Commented Mar 10, 2020 at 0:32

2 Answers 2

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.

2
  • There's also a potential call of operator-> on iElement, depending on what type it is. Commented Mar 9, 2020 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. Commented Mar 9, 2020 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;
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.