Ah, I see. I can explain it a bit more if the prior discussion was too advanced. It’s not so much a purist issue as it is a practical safeguard against dangerous coding patterns that introduce subtle and difficult-to-spot bugs.
In a nutshell, allowing temporary RAII containers to implicitly provide access to their resources is a dangerous design, as the pointer obtained from the implicit cast will be released at the end of the line. It’s similar to the reason std::string
won’t implicitly cast to const char*
, for example:
std::string someFunction();
const char *timebomb = someFunction().c_str();
where timebomb
is a pointer to freed memory.
There are two ways to fix your snippet with the proposed change, both are simple fixes:
- Explicitly Get() the pointer from the temporary (equivalent to calling
c_str()
). This says “I know there is a conversion here, and I’ve checked that it’s safe”.
Output->SetLines(vtkSmartPointer<vtkCellArray>::New().Get())
- Store the temporary in an named lvalue, and the implicit cast will still work:
auto lines = vtkSmartPointer<vtkCellArray>::New();
Output->SetLines(lines);
While these might seem contrived since SetLines
does reference counting, disabling the implicit cast for rvalues prevents more subtly buggy code like
vtkSmartPointer<vtkCellArray> someFunction();
vtkCellArray *oops = someFunction();
oops->Register(); // crash; the vtkSmartPointer dtor freed
// the vtkCellArray in the previous line.
from compiling. Like the std::string
example, the oops
pointer references freed memory and will cause problems, possibly much later in execution and in a different context after getting passed around. But by disabling the implicit cast for rvalues, we get an immediate compile error at the buggy line, instead of a phantom segfault in a random spot later in the program at runtime.