Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clang, std::shared_ptr and std::less/operator<

Tags:

c++

c++11

clang

Having the following code

#include <memory>

int main() {
    std::shared_ptr<int> ptr0( new int );
    std::shared_ptr<int> ptr1( new int );

    bool result = ptr0 < ptr1;
}

produces the following error when being compiled with clang (version 3.1, LLVM 3.1, Debian GNU/Linux Sid)

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/bits/shared_ptr.h:364:14: error: no matching function for call to object of type 'std::less<_CT>'
      return std::less<_CT>()(__a.get(), __b.get());
             ^~~~~~~~~~~~~~~~
foo.cpp:9:21: note: in instantiation of function template specialization 'std::operator<<int, int>' requested here
        bool result = ptr0 < ptr1;
                           ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/bits/stl_function.h:236:7: note: candidate function not viable: no known conversion from 'int *' to 'int *&&&' for
      1st argument;
      operator()(const _Tp& __x, const _Tp& __y) const
      ^

Compiling the same code with GCC (version 4.7.0) doesn't throw any error messages. Is there a reason why operator<() doesn't work for shared pointers in clang?

like image 225
stschindler Avatar asked Jun 20 '12 08:06

stschindler


People also ask

What does shared_ptr mean in C++?

The shared_ptr type is a smart pointer in the C++ standard library that is designed for scenarios in which more than one owner might have to manage the lifetime of the object in memory.

Is std :: shared_ptr Threadsafe?

std::shared_ptr is not thread safe. A shared pointer is a pair of two pointers, one to the object and one to a control block (holding the ref counter, links to weak pointers ...).

What happens if you move a shared_ptr?

By moving the shared_ptr instead of copying it, we "steal" the atomic reference count and we nullify the other shared_ptr . "stealing" the reference count is not atomic, and it is hundred times faster than copying the shared_ptr (and causing atomic reference increment or decrement).

Do you need to move a shared pointer?

Passing a shared pointer by rvalue reference is rarely necessary. Unless it's an implementation of move semantics for a shared pointer type itself, shared pointer objects can be safely passed by value.


1 Answers

clang++ and libstdc++ doesn't match perfectly yet. You could do one of the followings:

  • Switch to libc++ (by using clang++ -stdlib=libc++ -std=c++11 ...)
  • Apply the following patch to /usr/include/c++/4.7.0/type_traits (as documented in http://clang.llvm.org/cxx_status.html):

    Index: include/std/type_traits
    ===================================================================
    --- include/std/type_traits (revision 185724)
    +++ include/std/type_traits (working copy)
    @@ -1746,7 +1746,7 @@
    
       template<typename _Tp, typename _Up>
         struct common_type<_Tp, _Up>
    -    { typedef decltype(true ? declval<_Tp>() : declval<_Up>()) type; };
    +    { typedef typename decay<decltype(true ? declval<_Tp>() : declval<_Up>())>::type type; };
    
       template<typename _Tp, typename _Up, typename... _Vp>
         struct common_type<_Tp, _Up, _Vp...>
    

If you check bits/shared_ptr.h you did find a std::common_type, and the clang developers claim that it's actually a bug of libstdc++, although I don't believe a bug of libstdc++ alone would cause the non-existent type int*&&& to appear.

like image 82
kennytm Avatar answered Oct 18 '22 20:10

kennytm