5

In code snippet 1 below, mKnownSRList is defined as follows:

std::vector<EndPointAddr*> mKnownSRList;

I am getting a compilation error shown in code snippet 2. Can you tell me what's wrong with this code please? The content of the getTipcAddress() and compareTo functions are shown in code snippet 3 and 4 below.

CODE SNIPPET 1 (Compilation error is marked)

void 
ServiceRegistrarAPI::removeKnownSR(EndPointAddr & srEndPointAddr)
{
   auto last = 
   std::remove_if(mKnownSRList.begin(),
                  mKnownSRList.end(),
                 [srEndPointAddr]( EndPointAddr* o )
                 { 
                    //LINE 355 is the following
            EndPointTipcAddr myTipcAddress = srEndPointAddr.getTipcAddress();
                EndPointTipcAddr otherTipcAddress = o->getTipcAddress();

            return (myTipcAddress.compareTo(otherTipcAddress));
         });

    if(*last != nullptr)
    {
     delete *last;
    }

    mKnownSRList.erase(last, mKnownSRList.end());    
}

SNIPPET 2 (Compilation Error)

  ServiceRegistrarAPI.cpp:355:72: error: passing ‘const EndPointAddr’ as ‘this’   argument of ‘EndPointTipcAddr& EndPointAddr::getTipcAddress()’ discards qualifiers [-  fpermissive]

CODE SNIPPET 3 (getTipcAddress function)

EndPointTipcAddr & getTipcAddress() { return mTipcAddress; }

CODE NIPPET 4 (compareTo function)

  bool

  EndPointTipcAddr::compareTo(EndPointTipcAddr &rhs) 
  {     
      if( (mType == rhs.getType()) && (mInstanceNo == rhs.getInstanceNo()) )
      {
        return true;
      } 

      return false;
  }
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
F. Aydemir
  • 2,665
  • 5
  • 40
  • 60
  • 2
    Haven't considered this in detail, but I believe [this will be relevant](http://stackoverflow.com/questions/2835626/c0x-lambda-capture-by-value-always-const). – BoBTFish Mar 25 '13 at 15:18

3 Answers3

5

See S5.1.2.5:

The closure type for a lambda-expression has a public inline function call operator (13.5.4) whose parameters and return type are described by the lambda-expression’s parameter-declaration-clause and trailingreturn- type respectively. This function call operator is declared const (9.3.1) if and only if the lambdaexpression’s parameter-declaration-clause is not followed by mutable. It is neither virtual nor declared volatile. Default arguments (8.3.6) shall not be specified in the parameter-declaration-clause of a lambdadeclarator. Any exception-specification specified on a lambda-expression applies to the corresponding function call operator. An attribute-specifier-seq in a lambda-declarator appertains to the type of the corresponding function call operator. [ Note: Names referenced in the lambda-declarator are looked up in the context in which the lambda-expression appears. —end note ]

Basically, the implication is the operator() of the functor that is generated is const by default, and you've captured by value, and this captured variable is a member of the generated functor.

So, you've two options:

  1. Capture by reference, instead of by value.
  2. Change your lambda to the following (note the mutable following the parameter declaration clause):

    [srEndPointAddr](EndPointAddr* o) mutable { ... }

Nathan Ernst
  • 4,540
  • 25
  • 38
  • 1
    +1e6! At last someone explained why it really happened, not some mambo-jambo about everything else. – Red XIII Mar 25 '13 at 21:32
3

The predicate function (third argument of std::remove_if) is not allowed to modify the object. All methods called on the iterator must be const. See this documentation:

The function shall not modify its argument.

You can set getTipcAddress to be const if you are returning a copy of a value or a const pointer.

1

In short you get this error because you invoke a non-const method on a const instance in this case: srEndPointAddr is const but you invoke the non-const method getTipcAddress on it. The solution for you would be to declare this method const as it seems a simple getter and probably will not modify the object.

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176