Development

March 27, 2013

3 min read

ArticleFrom the archive

CategoriesDevelopment

Tagsc++/c++0x/c++11/vc++/visual studio

How to get confused by VC++

Today, I came across a confusing compilation error with MS VC++ using a std::unique_ptr with a custom deleter.

Here the code snippet:

#include <memory>
#include <string>

typedef void (*void_delete)(void *);

template<typename T>
void void_deleter(void * ptr) { delete reinterpret_cast<T*>(ptr); }

std::unique_ptr<void, void_delete> f1() {
return std::unique_ptr<void, void_delete>(new std::string("haha"), void_deleter);
}
std::unique_ptr<void, void_delete> f2() {
return std::unique_ptr<void, void_delete>(nullptr);
}

The compiler complains :

1  c:\program files (x86)\microsoft visual studio 10.0\vc\include\memory(2218): error C2338: unique_ptr constructed with null deleter pointer
2  1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\memory(2214) : while compiling class template member function 'std::unique_ptr::unique_ptr(std::nullptr_t)'
3  1> with
4  1> [
5  1> _Ty=void,
6  1> _Dx=void_delete
7  1> ]
8  1> c:\sources\source1.cpp(9) : see reference to class template instantiation 'std::unique_ptr' being compiled
9  1> with
10 1> [
11 1> _Ty=void,
12 1> _Dx=void_delete
13 1> ]

The gotcha is that the compiler complains of a reference to class template instantiation on line 9. This is the definition of f1().

However, the actual issue is on line 13 in the implementation of f2(). A std::unique_ptr is instantiated with a nullptr and no deleter. The nullptr constructor has a static_assert that protects from uninitialized function-pointer deleter. I wonder what could go wrong with an uninitialized function pointer … 😐

The compiler gives you the line of the first appearance of std::unique_ptr in the compilation unit not the actual line that causes the error … Easy enough to spot on a trimmed down example like this one. It tooks me quite some time to find in a code file with several hundred lines of code and many changes at once.