1

I feel that its unlikelier than not, but I'd like to see if a function can deduce its parameters from a trivially wrapped struct. For example:

struct wrapped_float
{
  float f;

  wrapped_float(float f) : f(f) {}
};

float saxpy(float a, float x, float y)
{
  return a * x + y;
}

int main()
{
  wrapped_float a = 1.1, x = 2.2, y = 3.3;

  auto result = saxpy(a, x, y); // ofc compile error
}

The motivation behind this is to make a lightweight wrapper around GDI calls with device context handles (HDC). There exists a lot of legacy code which uses HDCs and I'd like to refactor a lot of this code incrementally. My strategy is to make a lightweight wrapper around HDC like this:

#include <Windows.h>

struct graphics
{
  HDC dc;

  graphics(HDC dc) : dc(dc) {}

  void rectangle(int x, int y, int w, int h)
  {
    Rectangle(dc, x, y, x + w, y + h);
  }
};

void OnPaint(HDC dc)
{
  Rectangle(dc, 1, 2, 3, 4);
}

int main()
{
  HDC dc;
  // setup dc here
  graphics g = dc;

  OnPaint(g);
}

So that if g can be implicitly transformed to HDC, then all legacy code will normally compile, but I can slowly refactor code to become like this:

void OnPaint(graphics g)
{
  g.rectangle(1, 2, 3, 4);
}

Any recommendations are also welcome since this simply might not be possible in C++ (or any programming language).

Michael Choi
  • 610
  • 5
  • 22

1 Answers1

1

From the comments, I was not aware that C++ had a casting operator. The simple solution is to add:

struct graphics
{
  HDC dc;

  graphics(HDC dc) : dc(dc) {}

  void rectangle(int x, int y, int w, int h)
  {
    Rectangle(dc, x, y, x + w, y + h);
  }

  operator HDC()
  {
    return dc;
  }
};
Michael Choi
  • 610
  • 5
  • 22
  • 1
    Depending of `HDC` type, you might use `const` ref, and possibly marking or adding a method `const`: `operator const HDC&() const`. – Jarod42 Jan 25 '19 at 00:37
  • 1
    @Jarod42 What is the benefit of returning a const reference versus a copy of the handle? I will make the function const however – Michael Choi Jan 25 '19 at 00:44
  • 1
    Returning a reference avoid the overhead of making a copy of an object. A `const` reference ensures that the object cannot be modified. – Sam Varshavchik Jan 25 '19 at 01:16
  • 1
    @SamVarshavchik that's true but HDC is already like an opaque pointer and is very small (4 bytes). I wouldn't really see the benefit of passing by reference rather than copying by value. Could there be something else I am missing? – Michael Choi Jan 25 '19 at 01:21
  • 1
    Yes. Returning a `const reference` or `const` using an `inline` function generally prevents a fat-finger from typing `=` when you meant `==`, without any additional overhead, if using any modern C++ compiler. – Sam Varshavchik Jan 25 '19 at 01:24
  • @SamVarshavchik That is true for const, which I agree is a good idea; however, I am still wondering why passing a const reference of an HDC is better than returning a const HDC as a value. (sorry I forgot to tag you earlier) – Michael Choi Jan 25 '19 at 01:41
  • With a trivial POD it makes no difference, but with a non-trivial POD it does. But always using `const` references makes it possible to always have the option of redefining a former POD as more meaty object without then having to hunt down everywhere it's used and determine whether each usage needs to be replaced with a reference in order to avoid the penalty of copying it. – Sam Varshavchik Jan 25 '19 at 02:10