Page about vtkSmartPointer

Hi Everyone,

As I start learning VTK, I decided to collect together things about VTK smart poitners, which I found to be not obvious in the official tutorial. The page is available here:

https://github.com/DmitrySemikin/dsemikin_notes/wiki/vtk_smart_pointers

I hope, it may be helpful to anyone else.

Any comments / critic is also very welcome.

Dmitrii.

1 Like

This is very useful, thank you for taking the time to write all these up. It would be great if you could send a pull request that added this to the VTK textbook (source on github).

@ken-martin Who is responsible for the VTK textbook now? Do you accept pull requests on github?

I believe it is here now https://gitlab.kitware.com/vtk/textbook/-/tree/master/VTKBook

I know @amaclean has been doing some great ongoing work updating the examples there.

1 Like

Indeed, I did introduce a brief discussion of the vtk pointers in 3.11.2 VTK Pointer Classes in https://gitlab.kitware.com/vtk/textbook/-/tree/master/VTKBook

Also there has been a lot of good discussion here [ vtkNew and vtkSmartPointer](vtkNew and vtkSmartPointer) and here [ vtkSmartPointer and vtkNew in VTK’s API. Best practices?](vtkSmartPointer and vtkNew in VTK's API. Best practices?).

@amaclean @dsemikin it would be great if you could work together and make the VTK textbook contain all the relevant information from Dmitrii’s write-up and forum posts. The text can be reviewed and refined as part of the normal merge request review process. Making the VTK textbook a living document, maintained by community effort would ensure that the textbook remains useful and relevant.

Hi Everyone,

Thank you for your comments. Generally I have nothing agains the materials from the page being used somewhere else (e.g. in the book). The only problem, which I see is that I have really very little time to work on it (just couple of hours a week, probably).

This is also the reason, why the text is not even complete yet. And besides, it is IMO not in a very good shape. The whole thing tends to be overloaded with explicit explanations and generally not well balanced, which is probably not very good for the book. I am not even touching the fact, that the language itself is probably not so good.

Please, don’t get me wrong. It is not, that I don’t want to help. But I just don’t want, that you wait for something from my side and wonder, that nothing happens…

So I would say, I see two possible continuations, which may be anyhow productive:

  1. I just slowly continue to tweak my pages (hopefully there will be more some day, as I am going to learn and use some VTK in the future). And you can monitor, what is there and reuse it in whatever way you like (of course any reference would be nice). Or just forget about it :slight_smile:
  2. Or if you suggest some very specific not too big tasks, then I can try to do it, but someone else should coordinate it, control the overall quality, content etc. And I can still promice nothing about the timeline.

Just continue tweaking your own pages, that is the best approach. There is probably enough material in the book at present. Ultimately there may be a new version of the book, so by the time that happens, what you are currently doing will be in a really good state.

@lassoan If you want to start editing/updating the book feel free to start. At present I am very busy.

Some newer smart pointer related features that would be worth including:

vtkSmartPointer<SomeVtkObject> someVtkObjectManaged = vtkSmartPointer<SomeVtkObject>::Take(someVtkObjectUnmanaged);

can be simplified to:

auto someVtkObjectManaged = vtk::TakeSmartPointer(someVtkObjectUnmanaged);

The vtk::TakeSmartPointer helper uses template type deduction to remove the need to explicitly specify the pointer type, and combining it with auto eliminates a ton of boilerplate.

It’s especially helpful with the NewIterator type methods that return an object with a new reference count:

vtkCellArray *cellArray = ...;
auto cellIter = vtk::TakeSmartPointer(cellArray->NewIterator());
for (cellIter->GoToFirstCell();
     !cellIter->IsDoneWithTraversal();
     cellIter->GoToNextCell())
{
  ...
}

There’s a similar vtk::MakeSmartPointer that does the same thing, except that it does increment the reference count. vtkWeakPointer has a vtk::TakeWeakPointer helper as well.

1 Like

Following the suggestion from @AllisonVacanti…
You could shorten the creation of a smartpointer and make it appear less intimidating

auto someObject = vtkSmartPointer<vtkSomeObject>::New()

I have passed vtkSmartPointer managed objects as function arguments in std::async calls and it works as expected. All the reference counts are appropriately incremented/decremented.
Infact, you could use visual studio debugger to look at the std::atomic<int32_t> ReferenceCount variable as tasks are fired asynchronously. This could be a nice addition to your wiki.

Although I haven’t tried to get a vtkSmartPointer object from an std::future.

Edit : spelling

@AllisonVacanti

Thank you for your comment. This is definitely worth mentioning.

By the way, IMO usually the problem of such convenience methods is, that it is not easy to discover them. Probably one could add references to them into the Doxygen documentation of the corresponding methods of vtkSmartPointer and vtkWeakPointer.

By the way, do I understand correctly, that the sole purpose of vtk::MakeSmartPointer() is only to be used together with auto and avoid using template parameter in variable declaration. I.e. the two variants would be:

    vtkSmartPointer<SomeVtkObject> myObject(getRawPointer());
    // or 
    vtkSmartPointer<SomeVtkObject> myObject2 = getRawPointer();

    // vs

    auto myObject3 = vtk::MakeSmartPointer(getRawPointer());

… This is of course a matter of taste, but I personally prefer, when the types are explicitly present in the places, where variables are declared. In this sense using auto with vtkSmartPointer::New() is not bad, because in this case type is present on the right hand side. I.e.

    auto myObject = vtkSmartPointer<SomeVtkObject>::New(); // OK - type is explicitly present
    auto myObject2 = vtk::MakeSmartPointer(getRawPointer()); // I don't like - type is not explicitly present

Anyway, thank you for the comment.

@jaswantp

Regarding creation of vtkSmartPointer with auto - it is definitely absolutely valid way of doing things. Thus probably worth mentioning, so I will do it. Though I personally prefer the variant with vtkNew().

And regarding passing smart pointers to the functions as argument - this is expected. I also already described it on my page. The gochas come, when you try to return smart pointer from a function (actually in similar manner, as with raw pointers). Because in both cases the declaration of function does not allow to specify, if the ownership of returned object should be taken over by caller, or not. One solution for this in post-C++11 world is returning unique_ptr (or generally something not-copy-able, so that it is clear, that the ownership is passed further. But I don’t see how to naturally incorporate it into vtk. Besides the problem with inability to denote “keeping ownership” stays.

Another thing you might like to consider is C++ containers and the VTK smart pointers. There is some commentary in this example AmbientSpheres.

1 Like

// vtkNew, in contrast to vtkSmartPointer, has no assignment operator
// or copy constructor and owns one object for its whole lifetime.
// Thus vtkNew does not satisfy the CopyAssignable and CopyConstructible
// requirements needed for other std containers like std::vector or std::list.
// std::array, on the other hand, is a container encapsulating fixed size
// arrays so its elements do not need to be CopyAssignable and
// CopyConstructible.

Good news, this is no longer true – all of the VTK smart pointers, including vtkNew are usable with std::vector.

In C++11, the wording of std::vector<T>'s restrictions on the T type changed to remove the bits about CopyAssignable and CopyConstructible. The only remaining hard restriction is Erasable, any other requirements depend on how the container is actually used. While there are a few methods that explicitly require T to be copyable (e.g. std::vector::resize(size_type, const T&)), most only require that T is MoveInsertible.

All of the VTK smart pointers are MoveInsertible as of this commit and can be used in a std::vector, and vtkNew<T> can now be treated like any other move-only container. This came up a while ago in a post that discussed the changes. If you read that link, note that while you can return a vtkNew from a function, it’s easy to misuse since the issue mentioned in that thread was never resolved.

2 Likes