【问题标题】:Allowing both pre-computed and computed-on-the-fly results允许预先计算和即时计算结果
【发布时间】:2017-02-19 15:19:24
【问题描述】:

考虑:

template <typename T>
struct C {
    std::vector<int> f(const T &t) const {
        return t.f();
    }
};

T::f 必须计算所需的向量。但是,一些T 预先计算了向量,我们希望避免在这种情况下创建副本。这是我的尝试:

struct A {
    std::vector<int> f() const {
        std::vector<int> res{10, 20, 30}; // computing the vector.
        return res;
    }
};

struct B {
    const std::vector<int> &f() const {
        return v_; // returning reference to pre-computed vector.
    }
private:
    std::vector<int> v_{1, 2, 3};
};

template <typename T>
struct C {
    const std::vector<int> &f(const T &t) const {
        return t.f();
    }
};

int main() {
    using T = B; // For A, we get an error about returning reference to a local.
    C<T> c;
    T t;
    c.f(t);
    return 0;
}

正如main 中的注释所示,对于T=A,上面的代码是错误的,因为它返回了对局部变量的引用。我怎样才能同时容纳T=AT=B,这样预先计算的向量B::v_ 不会被复制?

【问题讨论】:

  • 您的代码已编译并可以运行:ideone.com/xedSqU
  • @Zefick 它只是 似乎 可以工作,但正如 OP 正确指出的那样,它返回对局部变量 UB 的引用。
  • 为什么不能将计算向量存储在 A 类中?您将解决复制和语法问题。
  • 使用decltype(auto)作为返回类型
  • @BlackMoses 在实际代码中,A::f 根据对象的状态计算向量。在这种实际情况下,将每次调用 A::f 的结果存储在成员变量中会很丑陋。

标签: c++ c++11 generic-programming const-reference


【解决方案1】:

使用decltype 使C::f 返回与T::f 完全相同的类型:

template <typename T>
struct C {
    auto f(const T &t) const -> decltype(t.f()) {
        return t.f();
    }
};

这将在T = A 时返回按值,在T = B 时返回const&amp;

wandbox example

【讨论】:

    【解决方案2】:

    您的尝试并未测试应有的内容。为了使预先计算的结果有用,它们需要是持久的。一个类需要同时进行计算和存储。

    例如,

    struct A {
        std::vector<int> const & f() const {
            if ( v_.empty() ) {
                v_ = {10, 20, 30}; // computing the vector.
            }
            return v_;
        }
    private:
        mutable std::vector<int> v_;
    };
    

    另一种架构是将所有结果存储在一个std::map&lt; X, std::vector &gt;(或unordered_map)中,如果有某种类型X定义了函数的域。

    【讨论】:

      猜你喜欢
      • 2018-03-03
      • 2014-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多