模板化成员函数和参数转发

templated member function and argument forwarding

我在我的 c++ playground 中玩容器,我遇到了相当技术性的问题。

我正在尝试为容器实现一个 emplace 方法。现在它应该接受一个已经构建的元素并将其传递给分配器构造方法。

我最终得到了三种方法,模板化 emplaceA 和一对 emplaceB1emplaceB2。所有工作都按预期进行。

我的问题是 emplaceA 没有明确说明 Arg 只能是 T(这就是我想要的)。 emplaceB1emplaceB2 在两个不同的地方提供了几乎相同的实现(我认为这是一个缺陷)。

有解决办法吗?

template<class T, class A> class container {
public:
    using allocator_traits  = typename std::allocator_traits<A>;
...
    template<class Arg> void emplaceA (int n, Arg&& arg){
        allocator_traits::construct(allocator_, data_+n, std::forward<Arg>(arg));};

    void emplaceB1(int n, const T& t){
        allocator_traits::construct(allocator_, data_+n, t);};

    void emplaceB2(int n, T&& t){
        allocator_traits::construct(allocator_, data_+n, std::move(t));};
...
};

要限制模板函数,您可以使用 sfinae 来防止发送不需要的类型。

在下面的示例中,我们将您的模板函数限制为仅当 Arg 可转换为 T 时才可调用。请注意,即使两种类型相同,is_convertible 也会起作用。

template<class Arg, std::enable_if_t<std::is_convertible<Arg, T>::value, int> = 0>
void emplaceA(int n, Arg&& arg){
    // ...
}

不要忘记包含 header <type_traits>


当然,如果你想检查发送的类型是否严格T,你可能想使用std::is_same和衰减类型。

template<class Arg, std::enable_if_t<std::is_same<std::decay_t<Arg>, T>::value, int> = 0>
void emplaceA(int n, Arg&& arg){
    // ...
}