use of new in relation to ref_ptr

42 views
Skip to first unread message

Robert Kiser

unread,
Aug 18, 2021, 4:31:21 PM8/18/21
to OpenSceneGraph Users
Hello All

My apologies in advance if my question is out of line (or just plain stupid).  Or has already been answered (couldn't find it if so).

I am an experienced programmer, but somewhat of a newbie as regards C++ and OSG.

A code snippet noting my question:

osg::ref_ptr<osg::GraphicsContext::Traits> pclsTraits;

pclsTraits = new osg::GraphicsContext::Traits();    //<<<<<<<<

//pclsTraits = osg::ref_ptr<osg::GraphicsContext::Traits>();
 //pclsTraits = std::make_unique<osg::GraphicsContext::Traits>();

pclsTraits->inheritedWindowData = new osgViewer::GraphicsWindowWin32::WindowData(hWnd);
pclsTraits->setInheritedWindowPixelFormat = true;
pclsTraits->doubleBuffer = true;
pclsTraits->windowDecoration = true;
pclsTraits->sharedContext = nullptr;
pclsTraits->supportsResize = true;

<pulled from a cookbook example I found>

My compiler (Visual Studio 2019 Ver. 16.11.1) emits warning C26409 on the line noted with <<<<<, saying that I should avoid calling new explicitly, instead suggesting that I use std::make_unique<T> instead.

When I tried that (see the 2nd commented line) the compiler emits an error saying: 'no operator "=" matches these operands'.

When I tried what was shown in the 1st commented line, it compiled fine with no warnings or errors but threw an exception when ran.

The code using the 'new' keyword works flawlessly.

What I am trying to do is make use of OSG's ref_ptrs but at the same time keep my compiler happy and minimize the warnings it emits.  I don't seem to be smart enough to make that happen.

Is there a modification to this code snippet that lets me set up a ref_ptr without using the keyword 'new'?

Thanks in advance,

Bob Kiser

Robert Osfield

unread,
Aug 19, 2021, 2:22:22 AM8/19/21
to OpenSceneGraph Users
Hi Robert,

The code is fine, the compiler is trying to be clever in case a possible errant use of C++, but isn't so clever as to see that the new'd object is being immediately assigned to a smart pointer. It should be possible to quieten down this type of warnings in the compiler.  Alternatively perhaps the compiler can be quietened down by doing:

   osg::ref_ptr<osg::Node> node(new osg::Node);

With the successor to the OpenSceneGraph, the VulkanSceneGraph I've also implemented an equivalent of osg::ref_ptr<> and also works with intrusive reference counting, but to help avoid the need for new calls I've implemented a Object::create() method that does the new and returns a vsg::ref_ptr<> for you. This allows you to do:

     auto node = vsg::Node::create(); // does a new Node and returns vsg::ref_ptr<vsg::Node>

I've also tweak vsg::ref_ptr<> so it doesn't allow straight C pointer assigned, to try and catch possible new misuse, I'm not entirely convinced it's a really sound restriction, but am trying it out to see what the impact is on day to day coding.

For the OSG, it's over 20 years old, and is in maintenance mode, so major changes that could break user code aren't on the table.  A tweak like adding a osg::Node::create() style usage might be possible to retrofit to the META_Node macro but replacing all new usage in the OSG code base would be a huge endeavour and likely fraught with potential error.

Cheers,
Robert.

Robert Kiser

unread,
Aug 19, 2021, 10:38:17 AM8/19/21
to OpenSceneGraph Users
Thanks Mr. Osfield for addressing this and clearing this up.  I am also relieved to learn that I am not a complete idiot.

I will look into the VulkanSceneGraph project.

Best regards,

Bob Kiser

Chris Djali / AnyOldName3

unread,
Aug 19, 2021, 6:04:39 PM8/19/21
to OpenSceneGraph Users
Hi,

It should be possible to make a templated free function something like this:

// skip the std::enable_if when C++11 isn't available, or shorten to std::enable_if_t if C++14 is available
template<typename T, typename... Args, typename std::enable_if<std::is_base_of<osg::Referenced, T>::value>::type* = nullptr>
osg::ref_ptr<T> create(Args&&... args)
{
    // if targeting multiple compilers, add #ifdefs to detect which is being used and disable the equivalent warning
    #pragma warning( push )
    #pragma warning( disable : 26409 )
        // skip std::forward and the universal reference (&&) if no C++11
        return osg::ref_ptr<T>(new T(std::forward<Args>(args)...));
    #pragma warning( pop )
}

You should be able to use this pretty much the same way as std::make_unique, and it should offer the same benefits, although I think as osg::ref_ptr takes a single argument in its constructor, you never had the risk of a leak if something threw an exception between the new and the assignment to the ref_ptr.

Hopefully this is interesting even if it doesn't end up being useful.

Chris
Reply all
Reply to author
Forward
0 new messages