I am trying to convert boost::object_pool usage on my old project to new visual studio 2019 project, I am using boost version 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);
}
got first error
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
]
should I need upgrade boost version? because previously this code compiled fine on vs2008, but not compiled on vs2019, this c++11 standard so confusing for me
can I get explanation this behavior?
Frankly, this code cannot have compiled under any compiler.
Note: I'm ignoring numerous typos, omitted semi-colons, omitted
template
declarators, typedefs and access specifiers to focus on the real issues.
You're passing *this
which is Material&
. However, the contruct
[sic] function takes a MaterialServer*
.
So, in fact, the commented line was closer, and makes sense IFF it were a member of MaterialServer
, not Material
.
It would make a lot more sense, logically, for the material server to "create new materials", anyways, and almost works:
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;
}
I say /almost/ because construct
takes its argument by mutable reference. That won't compile here (this
is NOT a mutable lvalue).
So, fixing that:
template <typename Arg1> T* construct(Arg1 sArg1) {
return m_sObjectPool.construct(sArg1);
}
Or, more generically:
template <typename... Arg> T* construct(Arg&&... sArg) {
return m_sObjectPool.construct(std::forward<Arg>(sArg)...);
}
We get "compiling code". We can't link it (the constructors aren't defined).
Adding some more imagined code:
#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();
}
Prints
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")