如何 link 带有调试符号的 libc++?

How to link libc++ with debug symbols?

我想让 std::optional 在用户请求空值时抛出异常。

#include <optional>
std::optional<int> oi;
int main(){
    *oi; // Must throw
}

c++ -std=c++17 test.cc && ./a.out

工作没有错误。

我发现在 clang 的 libc++ 实现中。

_LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
value_type& value()
{
    if (!this->__engaged_)
        __throw_bad_optional_access();
    return this->__val_;
}
_LIBCPP_INLINE_VISIBILITY
value_type&
operator*()
{
    _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
    return this->__val_;
}

然后我找到了llvm libc++ DebugMode

c++ -std=c++2a -D_LIBCPP_DEBUG -D_LIBCPP_DEBUG_USE_EXCEPTIONS ./main.cc && ./a.out 输出

Undefined symbols for architecture x86_64:
  "std::__1::__libcpp_db::__insert_c(void*)", referenced from:
      void std::__1::__libcpp_db::__insert_c<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) in main-eef9ea.o
  "std::__1::__libcpp_db::swap(void*, void*)", referenced from:
...

如何 link 带有调试符号的 libc++?

P.S.

 c++ --version
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

便携式解决方法。

#include <optional>

// The same as std::optional, but 
// throw and exception when ask for empty value.
// Use assert(0) when exceptions disabled.
template<typename T_>
struct Result : std::optional<T_>{
   using T = T_;
   using parent = std::optional<T_>;
   using parent::parent;
   using typename parent::value_type;
   using parent::operator bool;

   constexpr
   const value_type&
   operator*() const
   {
      ensure_is_engaged();
      return this->value();
   }

   value_type&
   operator*()
   {
      ensure_is_engaged();
      return this->value();
   }

private:
   void ensure_is_engaged(){
      if( bool is_disengaged = not bool(*this) )
       #if __EXCEPTIONS
         throw std::runtime_error("failed to get disengaged value from std::optional");
       #else
         assert(0 && "failed to get disengaged value from std::optional");
       #endif
   }
};

测试

int main()
{
   using std::cout, std::cerr, std::endl;
   Result<int> normal=1, fail;
   cout<<*normal<<*fail;
}

c++ -std=c++17 -fno-exceptions test.cc && ./a.out

1
Assertion failed: (0 && "failed to get disengaged value from std::optional"), function ensure_is_engaged, file ./result.hh, line 38.
fish: './a.out' terminated by signal SIGABRT (Abort)

c++ -std=c++17 test.cc && ./a.out 假设默认 -fexceptions

1
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: failed to get disengaged value from std::optional
fish: './a.out' terminated by signal SIGABRT (Abort)