2

I was trying to compile some code that uses Boost (1.49), with Clang(& libc++) from trunk. The problematic code boils down to the following:

#include <memory>
#include <boost/signals2.hpp>

int main()
{
    std::shared_ptr<int> s;
}

When compiled with Clang, the following message is emmited:

$ clang++ -I/home/alexander/usr/local/include --stdlib=libc++ -std=c++0x signals2-bug.cpp   -o signals2-bug
signals2-bug.cpp:6:26: error: implicit instantiation of undefined template
      'std::shared_ptr<int>'
    std::shared_ptr<int> s;
                         ^
/home/alexander/usr/local/include/boost/signals2/detail/foreign_ptr.hpp:24:30: note: 
      template is declared here
  template<typename T> class shared_ptr;
                         ^

The offending lines in boost/signals2/detail/foreign_ptr.hpp are:

#if !defined(BOOST_INTEL_STDCXX0X)
namespace std
{
  template<typename T> class shared_ptr;
  template<typename T> class weak_ptr;
}
#endif

Now who's to blame?

Two things come to mind:

  1. Why does the Boost.Signals header feel the need to declare an own shared_ptr? What's the gain?
  2. The line in Boost.Signals looks like a simple forward declaration. Why would that be problematic, if it comes after the template definition?

EDIT

This appears to be a Boost.Signals2 bug, because the declaration of things in the std:: namespace results in undefined behaviour, according to the ISO/IEC C++ 2011 Standard, section 17.6.4.2.1:

The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

A ticket in the Boost bug tracker has been created: https://svn.boost.org/trac/boost/ticket/6655

Please note, that a Clang bug also exists here: http://llvm.org/bugs/show_bug.cgi?id=10521 , however the implementor points to violation.

Follow-up for Googlers:

The problem was indeed a Boost bug. This changeset 77289 should fix the issue for Boost 1.50. The corresponding Bug in Clang was marked invalid.

Smi
  • 13,850
  • 9
  • 56
  • 64
fat-lobyte
  • 1,129
  • 1
  • 10
  • 16
  • 3
    Looks like a pretty clear bug in Boost.Signals2 to me. – ildjarn Mar 06 '12 at 00:21
  • @ildjarn: There shouldn't be a problem with *declaring* the templates, as long as the boost library doesn't attempt to *define* them. The error seems to say that there is no definition at all - apparently, including `` did not define `std::shared_ptr` as expected. – Mike Seymour Mar 06 '12 at 00:35
  • @Mike : Indeed, however the `#if` in the Boost code is clearly wrong (or at least less than ideal). – ildjarn Mar 06 '12 at 00:38
  • There allready is a Clang bug: http://llvm.org/bugs/show_bug.cgi?id=10521 , but an implementor states that declaring something in std:: is results in undefined behaviour. – fat-lobyte Mar 06 '12 at 09:49
  • What that looks like is a simple forward declaration that shouldn't confuse anyone. I'd rather think that by default CLang is not providing the tr1 `shared_ptr` in memory... Does your trivial `main` compile without the `` include? – Irfy Mar 06 '12 at 00:19
  • Yes, it does. Also, if i make the same declaration in the code myself, the compile fails with the same message, so it probably is a Clang bug. – fat-lobyte Mar 06 '12 at 09:30
  • Have you posted this on the boost users forum: http://boost.2283326.n4.nabble.com/ – mark Mar 06 '12 at 22:54
  • @MikeSeymour There is a problem simply declaring the templates, because an implementation of the C++ library actually has a lot of leeway in declarations, and forward declarations would have to match the choices made by the implementation. In this case libc++ puts things in an inline namespace, so a correct forward declaration would have to do the same. Another example would be an implementation that adds defaulted extra parameters to a standard function. Ideally there'd be standard headers available to forward declare as much of the standard library as possible. – bames53 Mar 09 '12 at 16:36
  • @mark: No, I didn't, bute the issue seems to have been fixed in [this revision](https://svn.boost.org/trac/boost/changeset/77289). – fat-lobyte Mar 11 '12 at 10:14

1 Answers1

0

The code in foreign_ptr.hpp is a redeclaration (if shared_ptr has already been defined), and as such not likely to cause problems (adding declarations to std is technically undefined behavior, but most compilers don't care since they don't really distinguish between standard library headers and other files). So the error can only be caused by shared_ptr being actually undefined.

Now libc++ obviously has a definition shared_ptr, so I can only suspect some C++03 library made it to the include path somehow and got preferred over libc++.

Philipp
  • 48,066
  • 12
  • 84
  • 109
  • Good Idea, but I checked the include paths (with the -v switch), and there is no other header before the one from libc++. – fat-lobyte Mar 06 '12 at 09:28
  • I think the key point is, that it is undefined behaviour! The standard mentions it in 17.6.4.2.1. I will edit to explain and report a Bug against Boost.Signals2. – fat-lobyte Mar 06 '12 at 09:46
  • This answer is not correct. The error is proximally caused by libc++ declaring shared_ptr in an inline namespace nested within std, and distally caused by the undefined behaviour of the boost code. – Richard Smith Mar 21 '12 at 05:23