Home > Blockchain >  Dynamically refer to different type of variables in c ?
Dynamically refer to different type of variables in c ?

Time:07-28

Here I want to simplify my c code from version 2 to version 1. In a language like Python, it's simple to refer to a different types of variables like version 1. How can I achieve similar code in c ?

#include <iostream>
#include <vector>

/* version 1: compile failed */
void display(std::vector<int> vi, std::vector<double> vd) {
  // error: operands to ?: have different types
  // ‘std::vector<double>’ and ‘std::vector<int>’
  auto& v = vi.empty() ? vd : vi;
  for (const auto &e : v) {
    std::cout << e << " ";
  }
}

/* version 2 */
void display(std::vector<int> vi, std::vector<double> vd) {
  if (!vi.empty()) {
    for (const auto &e : vi) {
      std::cout << e << " ";
    }
  } else {
    for (const auto &e : vd) {
      std::cout << e << " ";
    }
  }
}



int main(int argc, char *argv[]) {
  std::vector<int> vi{0, 1, 2};
  std::vector<double> vd{10., 11, 12};

  // one of vi, vd can be empty after some modifications
  ...

  display(vi, vd);
  return 0;
}

Supplement:

Here the print function is only an example. My main purpose is to create a reference to std::vector<int> or std::vector<double> according to whether they are empty or not. The following example may

#include <iostream>
#include <vector>

void process_1(std::vector<int> v) {
  for (const auto &e : v) {
    std::cout << e << " ";
  }
  std::cout << std::endl;
}

void process_1(std::vector<double> v) {
  double sum = 0;
  for (const auto &e : v) {
    sum  = e;
  }
  std::cout << sum << std::endl;
}

void process_2(std::vector<int>) {
  //...
}

void process_2(std::vector<double>) {
  //...
}

/* Version 2 */
int version_2(int argc, char *argv[]) {
  std::vector<int> vi{0, 1, 2};
  std::vector<double> vd{10., 11, 12};

  if (!vi.empty()) {
    process_1(vi);
  } else {
    process_1(vd);
  }

  // do something

  if (!vi.empty()) {
    process_2(vi);
  } else {
    process_2(vd);
  }

  return 0;
}

/* Version 1 */
int version_1(int argc, char *argv[]) {
  std::vector<int> vi{0, 1, 2};
  std::vector<double> vd{10., 11, 12};

  // in Python, it's easy to create a reference dynamically, eg:
  // ref = vd is len(vi) == 0 else vi
  auto &ref = vd if vi.empty() else vi;

  process_1(ref);
  // do something
  process_2(ref);

  return 0;
}

CodePudding user response:

Something along these lines, perhaps:

void display(const std::vector<int>& vi, const std::vector<double>& vd) {
  auto print_sequence = [](const auto& v) {
    for (const auto &e : v) {
      std::cout << e << " ";
    }
  }
  vi.empty() ? print_sequence(vd) : print_sequence(vi);
}

CodePudding user response:

What you're searching for is a visitor.

First version:

void display(std::vector<int> vi, std::vector<double> vd) {
    auto vis = [](const auto& v) {
        for (const auto& e : v) {
            std::cout << e << " ";
        }
    };
    if (vi.empty()) {
        vis(vd);
    } else {
        vis(vi);
    }
}

Note however, you don't necessarily need to pass two arguments, you might use a std::variant<std::vector<int>, std::vector<double>>:

void display(std::variant<std::vector<int>, std::vector< double>> vv) {
    auto vis = [](const auto& v) {
        for (const auto& e : v) {
            std::cout << e << " ";
        }
    };
    std::visit(vis, vv);
}

As a variant is constructible from any of the types, you can simply pass it either vi or vd.

This works with arbitrary number of types. Also, suggest passing arguments by const reference (e.g., const std::variant<std::vector< int>, std::vector< double>>&).

  • Related