如果 T 具有显式构造函数,则无法使用 emplace new 将元素添加到 container<T>

问题描述

我正在编写一个固定大小的容器类型,放置位置为新的。 当我测试它时,我发现如果类型 T 具有显式构造函数,我的“emplace_back()”之类的函数将无法编译。

这是一个代码示例(缺少删除调用等):

#include <iostream>

template <typename T>
struct TestType
{
   explicit TestType(T value) // removing explicit makes it a compileable code
   {
      std::cout << value << std::endl;
   }
};

template <typename... Args>
void emplace(TestType<int>* buffer,Args&&... args)
{
     // placement new // compile time error in this line
    new (buffer) TestType<int>(std::forward<TestType<int>>(args)...);
}

int main()
{
    TestType<int>* buffer;
    buffer = (static_cast<TestType<int>*>(::operator new(sizeof(TestType<int>) * 10)));
   
    emplace(buffer,5);
   
    return 0;
}

错误是: " 在 'void emplace(TestType*,Args&& ...) [with Args = {int}]' 的实例化中: 24:22:从这里需要 16:64:错误:没有匹配的函数调用'forward(int&)'"

stackoverflow 上有一些类似的问题,但这些问题主要是关于 std::map,可能我的问题不同。 (如果没有,我仍然不明白发生了什么。)

在(例如)std::vector emplace_back() 的情况下,它适用于任何带有显式 ctor 的 T 类型,为什么它不适用于我的容器类型? 这编译得很好:

#include <iostream>
#include <vector>

template <typename T>
struct TestType
{
   explicit TestType(T value)
   {}
};

int main()
{
    std::vector<TestType<int>> vector;
    vector.emplace_back(5);
     
    return 0;
}

感谢您的帮助!

解决方法

您将 TestType<int> 指定为 std::forward 的模板参数为 std::forward<TestType<int>>(args)...,这意味着您将参数转发为 TestType<int>。尝试将传递的参数隐式转换为 TestType<int>,这不起作用,因为转换构造函数被标记为 explicit

您应该指定 Args 作为 std::forward 的模板参数,即将参数转发为:

template <typename... Args>
void emplace(TestType<int>* buffer,Args&&... args)
{
    // placement new
    new (buffer) TestType<int>(std::forward<Args>(args)...);
    //                                      ^^^^
}