【问题标题】:Need I really use another template in this case在这种情况下我真的需要使用另一个模板吗
【发布时间】:2021-10-10 02:41:58
【问题描述】:
template<class Key, class Value>
class ThreadSafeMap
{
    std::mutex m_;
    std::map<Key, Value> c_;

public:
    Value get(Key const& k) {
        std::unique_lock<decltype(m_)> lock(m_);
        return c_[k]; // Return a copy.
    }

    template<class Value2>
    void set(Key const& k, Value2&& v) {
        std::unique_lock<decltype(m_)> lock(m_);
        c_[k] = std::forward<Value2>(v);
    }
};

Thread safe std::map: Locking the entire map and individual values

我刚刚阅读了上面的链接并找到了这段代码。制作线程安全映射看起来很棒。我知道在函数set中,我们在第二个参数v上使用了引用折叠规则。但是我不明白为什么我们需要导入另一个template&lt;class Value2&gt;,为什么我们不能简单地使用现有的模板class Value?

【问题讨论】:

    标签: c++ c++11 templates reference forwarding-reference


    【解决方案1】:

    v 应该被声明为forwarding reference,它只适用于模板。然后我们需要制作set本身的模板。

    (强调我的)

    转发引用是一种特殊的引用,它保留函数参数的值类别,从而可以通过std::forward 转发它。转发引用是:

    1. 函数模板的函数参数声明为对 cv 不合格同一函数模板的类型模板参数的右值引用:

    如果我们将set 声明为非模板:

    template<class Key, class Value>
    class ThreadSafeMap
    {
        ...
    
        // non-template member function
        void set(Key const& k, Value&& v) {
            std::unique_lock<decltype(m_)> lock(m_);
            c_[k] = std::forward<Value2>(v);
        }
    };
    

    v 将只是一个右值引用。

    【讨论】:

    • 我想他们会问为什么不在课堂上使用外部模板,即使用 value 模板值。这似乎也是“使用模板”。
    • 谢谢,但至少对我来说不是——你可以写 v2 将是一个右值引用,但不清楚哪个是正确的。从本质上讲,我认为您需要区分两种情况下发生的情况(在语言允许的意义上它们是有效的),也许有一个不同的用法示例。
    • TBH 我认为允许Value2 只是为了在自动转换规则等方面具有更大的灵活性,而不是右值-左值的东西。
    • 我想这可能是一个“什么是转发参考”问题,因为您的答案只有语言(半)专家才能清楚。我认为
    • 无论如何,被认为是最正确的一种,但我不确定这对 OP 来说是否足够。
    猜你喜欢
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 2012-07-01
    相关资源
    最近更新 更多