2
votes

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?

1
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.j6t
To save place, use one std::vector<int> ks;, and create auto g = [](auto f, int x, int k) ( return f(f(x)) + k);...Jarod42
@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.tanabe13f
@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).tanabe13f

1 Answers

1
votes

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.