使用std :: variant <t,std :: function <t()=“” >>作为灵活的输入而不是子类化

时间:2018-09-02 21:39:48

标签: c++ stl std-function std-variant

我有一个接受输入的类,有时我想通过分配一个变量来设置该输入,而在其他时候,我希望该类调用一个函数来获取其输入。

过去,我只是使用std::function<T()>作为输入,并设置了一个lambda以返回某些外部变量的值,但是我想摆脱{{1 }}。所以我想出了std::function

std::variant<T, std::function<T()>>

因此实现:

template <typename T>
using functionable = std::variant<T, std::function<T()>>;

// return the T or the result of the T() from the variant
template <typename T>
T get(const functionable<T>& f) {
  if (f.index() == 0)
    return std::get<0>(f);
  else
    return std::get<1>(f)();
}

并因此灵活地使用:

class SomeClass {
private:
  functionable<int> input_{0};

public:
  SomeClass(const functionable<int>& input) : input_{input} {}

  SomeClass& operator=(const functionable<int>& rhs) {
    input_ = rhs;
    return *this;
  }

  void print() { std::cout << get(input_) << '\n'; }

与仅使用SomeClass foo {42}; // init with assigned value foo.print(); foo = 101; // overwrite assigned value foo.print(); bool a{true}; // replace input value with input lambda foo { [this]{if(a) return 10; else return 20;} }; foo.print(); a = !a; // useful if input predicates change foo.print(); foo = 101; // replace std::function input with assigned int foo.print(); 作为输入和使用std::function<T()>作为固定输入值相比,这是一个改进吗?

另一种选择是为分配的输入和调用的输入创建单独的子类,但是当输入多个时,会导致组合爆炸。我还有其他选择吗?

1 个答案:

答案 0 :(得分:1)

从数学上讲,常数函数只是另一个函数。在这个C ++示例中,似乎没有动机将常量函数视为特例。除非您的大部分输入都是常量,否则性能可能大致相同。

此外,此functionable不能与std::generate一起使用,而std::function<>可以包装一个常数。当然,这可以通过将functionable包装在自己的类中或在另一个lambda中捕获来解决。但是,简单的解决方案可以做到的只是增加了复杂性。