在 visual studio 2019 中使用 boost::object_pool boost 版本 1.56 时出现问题

Problem using boost::object_pool boost version 1.56 with visual studio 2019

我正在尝试将旧项目的 boost::object_pool 用法转换为新的 visual studio 2019 项目,我使用的是 boost 版本 1.56

ObjectPool.h

class BOOST_OBJECT_POOL_CHECKER
{
  boost::object_pool< T > m_sObjectPool;
  
  template <class Arg1>
  T* contruct(Arg1& sArg1)
  {
     T* temp = m_sObjectPool.construct(sArg1);
     return temp;
  }
}

MaterialServer.h

class MaterialServer
{
   MaterialServer(dword serviceType, std::string path);
   Material* NEW_MATERIAL();
}

Material.h

class Material
{
  BOOST_OBJECT_POOL_CHECKER<Material> m_poolMATERIAL;

  Material(MaterialServer* pMatServer);
  
}

Material.cpp

Material* MaterialServer::NEW_MATERIAL()
{
   //Material* returnMaterial = m_poolMATERIAL.construct(this); << error on vs2019, not correct parameter
   Material* returnMaterial = m_poolMATERIAL.construct(*this);
}

遇到第一个错误

boost_1_56\boost\pool\detail\pool_construct_simple.ipp(19,1): error C2664: 'Material::Material(MaterialServer*)': cannot convert argument 1 from 'const T0' to 'MaterialServer *'
ObjectPool.h(68): message : see reference to function template instantiation 'Material *boost::object_pool<T,boost::default_user_allocator_new_delete>::construct<Arg1>(const T0 &)' being compiled
        with
        [
            T=Material,
            Arg1=MaterialServer,
            T0=MaterialServer
        ]

我需要升级boost版本吗?因为以前这段代码在 vs2008 上编译得很好,但在 vs2019 上没有编译,这个 c++11 标准让我很困惑

我可以解释一下这种行为吗?

坦率地说,这段代码无法在任何编译器下编译。

Note: I'm ignoring numerous typos, omitted semi-colons, omitted template declarators, typedefs and access specifiers to focus on the real issues.

您超过了 *this,即 Material&。但是,contruct [sic] 函数采用 MaterialServer*.

所以,事实上,注释行更接近,并且有道理 IFF 它是 MaterialServer 的成员,而不是 Material

从逻辑上讲,material 服务器“创建新的 materials”更有意义,而且几乎可以工作:

class Material {
  public:
    Material(MaterialServer* pMatServer);
};

class MaterialServer {
    BOOST_OBJECT_POOL_CHECKER<Material> m_poolMATERIAL;

  public:
    MaterialServer(dword serviceType, std::string path);
    Material* NEW_MATERIAL();
};

Material* MaterialServer::NEW_MATERIAL()
{
    Material* returnMaterial = m_poolMATERIAL.construct(this);
    return returnMaterial;
}

我说 /almost/ 因为 construct 通过可变引用来获取它的参数。这不会在这里编译(this 不是可变左值)。

所以,解决这个问题:

template <typename Arg1> T* construct(Arg1 sArg1) {
    return m_sObjectPool.construct(sArg1);
}

或者,更笼统地说:

template <typename... Arg> T* construct(Arg&&... sArg) {
    return m_sObjectPool.construct(std::forward<Arg>(sArg)...);
}

我们得到“编译代码”。我们不能 link 它(未定义构造函数)。

再补充一些想象中的代码:

Live On Coliru

#include <boost/pool/object_pool.hpp>
#include <iomanip>
#include <iostream>
#include <string>
#include <atomic>

using dword = uint32_t;

template <typename T> class BOOST_OBJECT_POOL_CHECKER {
    boost::object_pool<T> m_sObjectPool;

  public:
    template <typename... Arg> T* construct(Arg&&... sArg)
    {
        return m_sObjectPool.construct(std::forward<Arg>(sArg)...);
    }
};

class MaterialServer; // forward declare

class Material {
  public:
    Material(MaterialServer* pMatServer);
};

class MaterialServer {
    BOOST_OBJECT_POOL_CHECKER<Material> m_poolMATERIAL;

    dword _serviceType;
    std::string _path;

  public:
    MaterialServer(dword serviceType, std::string path)
        : _serviceType(serviceType)
        , _path(path)
    {
    }

    Material* NEW_MATERIAL();

    dword getServiceType() const { return _serviceType; }
    std::string_view getPath() const { return _path; }
};

Material* MaterialServer::NEW_MATERIAL()
{
    Material* returnMaterial = m_poolMATERIAL.construct(this);
    return returnMaterial;
}

Material::Material(MaterialServer* pMatServer)
{
    static std::atomic_int id{0};
    std::cout << "Material " << id++ << " from server ("
              << pMatServer->getServiceType() << ", "
              << std::quoted(pMatServer->getPath()) << ")\n";
}

int main() {
    MaterialServer a(123, "Material/a/resource");
    MaterialServer b(234, "Material/b/resource");

    a.NEW_MATERIAL();
    a.NEW_MATERIAL();
    b.NEW_MATERIAL();
    a.NEW_MATERIAL();
}

版画

Material 0 from server (123, "Material/a/resource")
Material 1 from server (123, "Material/a/resource")
Material 2 from server (234, "Material/b/resource")
Material 3 from server (123, "Material/a/resource")