【问题标题】:Problem using boost::object_pool boost version 1.56 with visual studio 2019在 Visual Studio 2019 中使用 boost::object_pool boost 1.56 版时出现问题
【发布时间】:2021-02-11 13:20:44
【问题描述】:

我正在尝试将旧项目上的 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();
}

材料.h

class Material
{
  BOOST_OBJECT_POOL_CHECKER<Material> m_poolMATERIAL;

  Material(MaterialServer* pMatServer);
  
}

材料.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标准让我很困惑

我能解释一下这种行为吗?

【问题讨论】:

  • 在阅读之前。请升级提升。使用 2015 年的版本和更新的编译器是没有意义的。很明显,编译器不在支持的平台列表中
  • "Your code was missing some semicolons here and there, and the union was missing member names." - 这是你的问题中相当烦人的模式,@navirius。如果您想发布一个指向您的实际代码库(github?)的链接,我宁愿按原样查看它......当然,这可能工作量太大,但我想它会比去更快一个一个地处理这些,每次都得到一张扭曲的代码图片。

标签: c++ boost visual-studio-2019 visual-studio-2008-sp1


【解决方案1】:

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

注意:我忽略了许多拼写错误、省略了分号、省略了 template 声明符、typedef 和 access specifiers,以专注于真正的问题。

您正在传递*this,即Material&amp;。但是,contruct [原文如此] 函数采用 MaterialServer*

因此,事实上,注释行更接近,并且如果它是 MaterialServer 的成员,而不是 Material 的成员,则有意义。

无论如何,从逻辑上讲,材料服务器“创建新材料”会更有意义,而且几乎可以工作:

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)...);
}

我们得到“编译代码”。我们无法链接它(构造函数未定义)。

添加更多想象的代码:

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")

【讨论】:

  • 你对 NEW_MATERIAL 函数是正确的,编辑我的问题
  • 上次编辑是 5 小时前。我没看到。另外,请避免以使现有答案无效的方式编辑问题
  • 我能解释一下“template ”和“template ”的区别吗?
  • 是的,没有区别。只是typename 更通用(它不排除“int”、“double”或“struct X*”)。这真的是品味问题。 To get /very/ technical there WAS a difference only in the context of [template template arguments before c++17,但我们不要偏离轨道]
  • 这个公认的答案,尤其是 BOOST_OBJECT_POOL_CHECKER 类中的“构造”函数
猜你喜欢
  • 2020-04-16
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
相关资源
最近更新 更多