【问题标题】:Using std::variant<T, std::function<T()>> as a flexible input instead of subclassing使用 std::variant<T, std::function<T()>> 作为灵活的输入而不是子类化
【发布时间】:2018-09-02 21:39:47
【问题描述】:

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

在过去,我只是使用 std::function&lt;T()&gt; 作为输入,并设置一个 lambda 来返回某个外部变量的值,但我正试图摆脱对 std::function 的过度使用。于是我想出了std::variant&lt;T, std::function&lt;T()&gt;&gt;

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&lt;T()&gt; 输入和使用 foo = []{return 42;} 固定输入值相比,这是否有所改进?

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

【问题讨论】:

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


    【解决方案1】:

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

    此外,functionable 不能与 std::generate 一起使用,而包装常量的 std::function&lt;&gt; 可以。这当然可以通过将functionable 包装在它自己的一个类中或在另一个 lambda 中捕获一个来解决。但是,当简单的解决方案可行时,它只会增加复杂性。

    【讨论】:

      猜你喜欢
      • 2015-07-23
      • 1970-01-01
      • 2019-04-14
      • 1970-01-01
      • 2011-06-30
      • 2023-02-16
      • 1970-01-01
      • 2016-11-10
      • 1970-01-01
      相关资源
      最近更新 更多