1

Using repl, it appears to be completely legal, however is there any undefined behavior/compiler-specific issues at play here?

https://repl.it/repls/ContentPutridMacro

googling for the 'this' usage inside of a header doesn't seem to turn up anything useful. Here is a copy of my example if the repl link doesn't work.

Multiplier.h :

#include <functional>

class Multiplier
{
public:
  Multiplier(int i);

  void multiplyBy(int j);

  std::function<void()> multiplyBy100 = std::bind(&Multiplier::multiplyBy, this, 100);

private:
  int priv;
};

Multiplier.cpp:

#include <stdio.h>
#include "Multiplier.h"

Multiplier::Multiplier(int i) : priv(i)
{
  // empty
}

void Multiplier::multiplyBy(int j)
{
   printf("value = %d\n", priv * j);
}

How I'm understanding this currently is that when you create an instance of Multiplier, say

Multiplier m(25);

It will create a Multiplier object and put all its member variables on to the stack, one of them being

std::function<void()> multiplyBy100

meaning that instance can know what value 'this' should be pointing to. Maybe I'm overthinking this but I just have never seen something comparable before.

Thank you for the help!

Community
  • 1
  • 1
  • There is nothing that prevents any language keyword being used in a header file. To answer, your question though, a default member initialiser is executed in context of a constructor initialisation list (and ignored by any constructor that explicitly initialises the same member) and `this` is valid in that context. That suggests using `this` is valid in the usage you describe. It is completely subjective as to whether it is *better* than (say) using an initialiser list in a constructor or constructor delegation. – Peter May 21 '20 at 00:56
  • You could do `std::function multiplyBy100 = [this]{ multiplyBy(100); };`, I believe it is generally preferred style now to use lambdas instead of bind calls – M.M May 21 '20 at 00:59
  • Maybe this class will have incorrect behaviour on the default copy/move constructor and assignment though, as copying the `std::function` object will result in an object that still multiples the original object it was set up for (and then UB if that object no longer exists) – M.M May 21 '20 at 01:01
  • I updated the repl to invoke the copy constructor, and then modified the original (deleted/re-assigned), but the copied instance retained the original value. Kind of difficult to force undefined behavior though. Thanks for the insight! Out of curiosity, why are lambdas preferred over bind? Is it just a stylistic choice or is there actually some benefit? – chuck_schuldiner May 21 '20 at 01:16

1 Answers1

1

You can use this inside a non-static data member initializer. The C++17 standard explicitly mentions this in paragraph [expr.prim.this]/3.

Whether this appears inside a header is irrelevant. A header is just a piece of code that gets "pasted" into another file when included.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312