I want to create a create a compile time vector that associates a type and a lambda with an index

Hi,

This is the code I have now:

1
2
3
4
5
6
7
8
9
10
11
12
13
	auto processingObj = process(selectCriteria, lines);
	switch (col)
	{
	case Columns::Date:
	{
		processingObj.filter<date::day_point>(selectViaDate);
	}
	break;
	case Columns::Concept:
	{
		processingObj.filter<std::string>(selectViaConcept);
	}
	break;


Both selectViaDate and selectViaConcept are lambdas. I want to eliminate this switch to something like:

 
processingObj.filter<col>();


Since each column col has a pair (Type, lambda) uniquely associated with it.

Any ideas?

Thanks
Juan
Since lambdas are objects, just return them via a function that takes col as a parameter. If you want it to be compile time, use metaprogramming with templates. Not sure if constexpr works in this case, but I may be wrong.
Last edited on
Just one problem Golden Lizard, if I create a function like so:

auto getLambda(int col) {///...}

it will not work because the different lambdas have different types.

See?

Thanks,
Juan
Last edited on
col can be used as the index into tuple whose second element is a lambda. We can use meta-programming to extract the right one.

Do you have Boost::Fusion available to you in this project? It is designed exactly for this kind of problem.
Last edited on
Ok mbozzi!! I do have Boost::Fusion but have never used it! Can you point me to where you think it would be most useful?

Thanks!!
Juan
Fusion::map looks promising.

Here's an example of how to do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
namespace date { struct day_point { int value; }; }

# include <functional>
template <typename T>
using predicate = std::function<bool(T const&)>;

# include <boost/fusion/algorithm/query/find.hpp>
# include <boost/fusion/include/find.hpp>
# include <boost/fusion/include/map.hpp>
# include <boost/fusion/include/pair.hpp>
# include <boost/fusion/include/sequence.hpp>
# include <boost/fusion/include/vector.hpp>

namespace fsn = boost::fusion;

# include <algorithm>
# include <random>
# include <vector>

class ProcessingObject {
public:
  template <typename FilterBy>
  void filter_out() {
    auto  lambda = filter_at<FilterBy>();
    auto& column = get_column<FilterBy>();
    column.erase(std::remove_if
                 (column.begin(), column.end(), lambda),
                 column.end());
  }

  template <typename T>
  std::vector<T>& get_column() {
    auto res = fsn::find<std::vector<T>>(columns);
    if (res == fsn::end(columns)) {
      /* No matching column */
    }
    return *fsn::find<std::vector<T>>(columns);
  }

  template <typename FilterBy>
  auto& filter_at() {
    return fsn::at_key<FilterBy>(filter_map);
  }

private:
  fsn::map<fsn::pair<date::day_point, predicate<date::day_point>>,
           fsn::pair<std::string,     predicate<std::string>>>
  filter_map {};

  fsn::vector<std::vector<date::day_point>,
              std::vector<std::string>> columns;
};

# include <iostream>
# include <random>
int main (int, char **) {
  auto obj = ProcessingObject{};
  /* Fill some columns. */
  auto &strings = obj.get_column<std::string>();
  auto &days    = obj.get_column<date::day_point>();

  strings.emplace_back("whatever");
  strings.emplace_back("blah");
  strings.emplace_back("foobar");
  for (auto i = 0; i < 10; ++i)
    days.emplace_back(date::day_point{i});

  /* Set up some filter functions for each associated column */
  auto day_point_filter = [](auto day){ return day.value  < 7; };
  auto str_filter       = [](auto str){ return str.size() > 4; };
  obj.filter_at <std::string>()     = str_filter;
  obj.filter_at <date::day_point>() = day_point_filter;

  /* Display the contents of some columns */
  for (auto elt: obj.get_column<std::string>())
    std::cout << elt << "\n";
  for (auto elt: obj.get_column<date::day_point>())
    std::cout << elt.value << "\n";

  std::cout << "Filtering out things according to our lambdas" << "\n";
  /* Filter according to the lambda associated with each type. */
  obj.filter_out<std::string>();
  obj.filter_out<date::day_point>();

  for (auto elt: obj.get_column<std::string>())
    std::cout << elt << "\n";
  for (auto elt: obj.get_column<date::day_point>())
    std::cout << elt.value << "\n";
}

Big thanks mbozzi !! Incredible example!!

Juan
Topic archived. No new replies allowed.