2

I have defined a struct A with a member f that holds a lambda function. The type is given as a template parameter, and f is initialized in the constructor using an argument to the constructor. The following code has worked well.

template <typename f_t>
struct A {
  f_t f;                                             // (1)
  int k;
  A(f_t arg_f, int arg_k) : f(arg_f), k(arg_k) {}    // (2)
  int g(int x) { return f(f(x)) + k; }
};

Now I want to have a vector of struct A with the same lambda function.

int main() {
  int p, q; std::cin >> p >> q;
  auto f1 = [&](int x) -> int { return p * x + q; };
  auto f2 = [&](int x) -> int { return p * x - q; };
  std::vector<A<decltype(f1)>> vec_a1;               // (3)
  std::vector<A<decltype(f2)>> vec_a2;
  for (int i = 0; i < 10000; i++) {
    int k; std::cin >> k;
    vec_a1.emplace_back(f1, k);
    vec_a2.emplace_back(f2, k);
  }
  // ....

  return 0;
}

With this code, I think that member f of struct A should rather be static to save space. But if I change Line (1) to:

static f_t f;

then, naturally, it cannot be initialized in the constructor. Line (2) produces the following error:

error: ‘f_t A<f_t>::f’ is a static data member; it can only be initialized at its definition

The assignment is not allowed, either, because of the deleted assignment operator. If I add the following after Line (3):

A<decltype(f1)>::f = f1

the following error is reported:

error: use of deleted function 'main(int, char**)::<lambda(int)>& main(int, char**)::<lambda(int)>::operator=(const main(int, char**)::<lambda(int)>&)'

(It seems that it would lead to a linker error but for this error.)

How can I initialize the member f?

4
  • Having a static member that is initialized (or better: assigned to) in the constructor sounds like a wrong design. Get your design straight first, then you most likely will not have to ask that question. Commented Jan 16, 2021 at 9:36
  • To save place, use one std::vector<int> ks;, and create auto g = [](auto f, int x, int k) ( return f(f(x)) + k);... Commented Jan 16, 2021 at 10:28
  • @j6t: I do not want to initialize the static member f in the constructor at all. I just want to know how I can initialize f with f1 or assign f1 to f. Commented Jan 18, 2021 at 6:57
  • @Jarod42: In my real program, f is heavily used in other member functions of struct A. I just want to turn it to a static member (if it is at all possible). Commented Jan 18, 2021 at 6:57

1 Answer 1

1

To save place, you might redesign to something like:

template <typename F>
struct A {
  F f;
  std::vector<int>* v;
  A(F f, std::vector<int>* v) : f(f), v(v) {}
  int g(int i, int x) { return f(f(x)) + v[i]; }
};

nt main() {
  int p, q; std::cin >> p >> q;
  auto f1 = [&](int x) -> int { return p * x + q; };
  auto f2 = [&](int x) -> int { return p * x - q; };
  std::vector<int> v;
  for (int i = 0; i < 10'000; i++) {
    int k; std::cin >> k;
    v.emplace_back(k);
  }
  A<decltype(f1)> a1(f1, &v);
  A<decltype(f2)> a2(f2, &v);
  // ...
}

So you store each values f1, f2 and ks only once.

Whereas you store 10.000 time f1, f2 and each ks twice.

It might be a little less convenient to use. There are generally a trade-of between the different kind of optimizations (memory/speed) themselves, safety and readability/simplicity.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. I think I have got your point. By the way, Is it correct that there is no way to initialize f with f1 or assign f1 to f if I make f static? I still want to know this point.
Pre-C++20, lambda are not default constructible, and anyway, as you capture by reference, it would not be. You might have global std::function instead which is assignable/default constructible, but has its own drawbacks.
I understand. Thank you for your answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.