0

This is kind of a follow up to this question, where I asked how I could tersely turn a template and/or overloaded function into a function object.

The accepted answer was you can't do without macro, which is correct. Then I found that such a macro is offered by Boost, in the form of the BOOST_HOF_LIFT and BOOST_HOF_LIFT_CLASS macros.

It turns out, however, that there are other "named things" you can't pass around. I don't know all of them, but one of them is constructors. And Boost.Hof offers a way to lift them to, via boost::hof::construct.

The point is that not even boost::hof::construct can deal with a class without a user-declared constructor. For intance, given

struct Foo {
    int foo;
};

the call boost::hof::construct<Foo>()(3) simply doesn't work. (Adding the constructor Foo(int) {} in Foo makes it work; that's what boost::hof::construct is for, after all.)

Surely, in simple cases like the one above I could just write

auto makeFoo = [](int x){ return Foo{x}; };

but if I want to support any type, I have to take care of perfect forwarding and variadic arguments.

Is there a library offering this feature already? It doesn't look like Boost.Hof does...

Enlico
  • 23,259
  • 6
  • 48
  • 102
  • At this point, there's not much reason to provide such functionality. C++20 allows aggregate initialization through constructor `()` syntax, so such a thing would only be useful for pre-C++20 projects. – Nicol Bolas Nov 16 '21 at 17:28

1 Answers1

2

If you want a function object that constructs an object of some type T given some parameters, even if T is an aggregate, that's not difficult to write in C++17:

template<typename T>
struct lifted_construct
{
  template<typename ...Args>
  T operator() (Args&& ...args)
  {
    if constexpr(std::is_aggregate_v<T>)
    {
      return T{std::forward<Args>(args)...};
    }
    else
    {
      return T(std::forward<Args>(args)...);
    }
  }
};

Of course, in C++20, you can use () syntax even for aggregates.

Enlico
  • 23,259
  • 6
  • 48
  • 102
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • I guess `boost::hof::construct` doesn't use such a technique because Boost.Hof is meant to be a C++11/C++14 library, and [`std::is_aggregate_v`](https://en.cppreference.com/w/cpp/types/is_aggregate) is from C++17 (and, if I understand correctly, it can't be implemented in the language and therefore needs compiler support). – Enlico Nov 16 '21 at 18:13