使用std :: variant >作为灵活的输入而不是子类化

问题描述 投票:1回答:1

我有一个接受输入的类,有时候我想通过赋值变量来设置输入,有时我想让类调用一个函数来获取它的输入。

在过去,我刚刚使用std::function<T()>作为输入,并设置一个lambda来返回一些外部变量的值,但我试图避免过度使用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()>作为输入并使用foo = []{return 42;}作为固定输入值的改进?

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

c++ stl std-function std-variant
1个回答
1
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.