Inheriting from std::error_category with libc++

Hi All,

I've come across what I believe is a problem in libc++.

While working through Chris Kohlhoff's blog entries about system_error (Thinking Asynchronously in C++: System error support in C++0x - part 4) I discovered that it's not possible to inherit from std::error_category in libc++.

The following small test case compiles correctly under G++ 4.6.3 on Linux with libstdc++, but fails under Mac OS X Mountain Lion with Xcode 4.5 (Apple clang version 4.0 (tags/Apple/clang-421.0.60) (based on LLVM 3.1svn)).

#include <system_error>
#include <string>

namespace {
class test_category_impl
    : public std::error_category
{
public:
    virtual const char * name() const noexcept
    {
        return "test_category";
    }
    virtual std::string message(int ev) const
    {
        return "default";
    }
};
}

const std::error_category & test_category()
{
    static test_category_impl inst;
    return inst;
}

With G++ on Linux I'm compiling with:
  g++ -c -std=c++0x -o bugtest.o bugtest.cpp

This works as expected.

With clang on the Mac I'm compiling with:
  clang++ -c -std=c++11 -stdlib=libc++ -o bugtest.o bugtest.cpp

This gives the following error:
$ clang++ -c -std=c++11 -stdlib=libc++ -o bugtest.o bugtest.cpp
bugtest.cpp:22:31: error: call to implicitly-deleted default constructor of '<anonymous>::test_category_impl'
    static test_category_impl inst;
                              ^
bugtest.cpp:5:7: note: 'test_category_impl' defined here
class test_category_impl
      ^
1 error generated.

All literature I've come across indicates that I should be able to inherit from error_category and the wording in the draft of N3242 states "Classes may be derived from error_category to support categories of errors in addition to those defined in this International Standard." The libc++ implementation seems quite deliberate in its intent to not allow the user to inherit this class (it uses a private default constructor and a private friend class called __do_message internally within the library).

So have things changed? Are we no longer intended to be able to create error_category subclasses, or is this a bug?

Thanks,
Michael

This looks like a standards bug. I filed a LWG issue on it here:

http://cplusplus.github.com/LWG/lwg-active.html#2145

but the lwg has not yet commented on the issue. Generally my policy is to wait until the lwg addresses the issue before changing the libc++ implementation. But in this case I'm tempted to go ahead and fix this in anticipation of the lwg accepting the issue as proposed.

Does anyone have any /objections/ to me pushing this fix in now (as proposed in http://cplusplus.github.com/LWG/lwg-active.html#2145)?

Howard

Hi All,

I've come across what I believe is a problem in libc++.

While working through Chris Kohlhoff's blog entries about system_error (Thinking Asynchronously in C++: System error support in C++0x - part 4) I discovered that it's not possible to inherit from std::error_category in libc++.

The following small test case compiles correctly under G++ 4.6.3 on Linux with libstdc++, but fails under Mac OS X Mountain Lion with Xcode 4.5 (Apple clang version 4.0 (tags/Apple/clang-421.0.60) (based on LLVM 3.1svn)).

#include <system_error>
#include <string>

namespace {
class test_category_impl
  : public std::error_category
{
public:
  virtual const char * name() const noexcept
  {
      return "test_category";
  }
  virtual std::string message(int ev) const
  {
      return "default";
  }
};
}

const std::error_category & test_category()
{
  static test_category_impl inst;
  return inst;
}

With G++ on Linux I'm compiling with:
g++ -c -std=c++0x -o bugtest.o bugtest.cpp

This works as expected.

With clang on the Mac I'm compiling with:
clang++ -c -std=c++11 -stdlib=libc++ -o bugtest.o bugtest.cpp

This gives the following error:
$ clang++ -c -std=c++11 -stdlib=libc++ -o bugtest.o bugtest.cpp
bugtest.cpp:22:31: error: call to implicitly-deleted default constructor of '<anonymous>::test_category_impl'
  static test_category_impl inst;
                            ^
bugtest.cpp:5:7: note: 'test_category_impl' defined here
class test_category_impl
    ^
1 error generated.

All literature I've come across indicates that I should be able to inherit from error_category and the wording in the draft of N3242 states "Classes may be derived from error_category to support categories of errors in addition to those defined in this International Standard." The libc++ implementation seems quite deliberate in its intent to not allow the user to inherit this class (it uses a private default constructor and a private friend class called __do_message internally within the library).

So have things changed? Are we no longer intended to be able to create error_category subclasses, or is this a bug?

This looks like a standards bug. I filed a LWG issue on it here:

http://cplusplus.github.com/LWG/lwg-active.html#2145

but the lwg has not yet commented on the issue. Generally my policy is to wait until the lwg addresses the issue before changing the libc++ implementation. But in this case I'm tempted to go ahead and fix this in anticipation of the lwg accepting the issue as proposed.

Does anyone have any /objections/ to me pushing this fix in now (as proposed in http://cplusplus.github.com/LWG/lwg-active.html#2145)?

This looks like exactly what I'm experiencing. As an aside, the libstdc++ folks have declared the default constructor as protected, which might be a better choice.

Michael

Oh, never mind. It appears I *already* did that: :slight_smile:

Hi All,

I've come across what I believe is a problem in libc++.

While working through Chris Kohlhoff's blog entries about system_error (Thinking Asynchronously in C++: System error support in C++0x - part 4) I discovered that it's not possible to inherit from std::error_category in libc++.

The following small test case compiles correctly under G++ 4.6.3 on Linux with libstdc++, but fails under Mac OS X Mountain Lion with Xcode 4.5 (Apple clang version 4.0 (tags/Apple/clang-421.0.60) (based on LLVM 3.1svn)).

#include <system_error>
#include <string>

namespace {
class test_category_impl
: public std::error_category
{
public:
virtual const char * name() const noexcept
{
     return "test_category";
}
virtual std::string message(int ev) const
{
     return "default";
}
};
}

const std::error_category & test_category()
{
static test_category_impl inst;
return inst;
}

With G++ on Linux I'm compiling with:
g++ -c -std=c++0x -o bugtest.o bugtest.cpp

This works as expected.

With clang on the Mac I'm compiling with:
clang++ -c -std=c++11 -stdlib=libc++ -o bugtest.o bugtest.cpp

This gives the following error:
$ clang++ -c -std=c++11 -stdlib=libc++ -o bugtest.o bugtest.cpp
bugtest.cpp:22:31: error: call to implicitly-deleted default constructor of '<anonymous>::test_category_impl'
static test_category_impl inst;
                           ^
bugtest.cpp:5:7: note: 'test_category_impl' defined here
class test_category_impl
   ^
1 error generated.

All literature I've come across indicates that I should be able to inherit from error_category and the wording in the draft of N3242 states "Classes may be derived from error_category to support categories of errors in addition to those defined in this International Standard." The libc++ implementation seems quite deliberate in its intent to not allow the user to inherit this class (it uses a private default constructor and a private friend class called __do_message internally within the library).

So have things changed? Are we no longer intended to be able to create error_category subclasses, or is this a bug?

This looks like a standards bug. I filed a LWG issue on it here:

http://cplusplus.github.com/LWG/lwg-active.html#2145

but the lwg has not yet commented on the issue. Generally my policy is to wait until the lwg addresses the issue before changing the libc++ implementation. But in this case I'm tempted to go ahead and fix this in anticipation of the lwg accepting the issue as proposed.

Does anyone have any /objections/ to me pushing this fix in now (as proposed in http://cplusplus.github.com/LWG/lwg-active.html#2145)?

Oh, never mind. It appears I *already* did that: :slight_smile:

-----------------------
r153194 | hhinnant | 2012-03-21 12:18:57 -0400 (Wed, 21 Mar 2012) | 1 line

It appears that the standard accidentally removed the default constructor for error_category. I'm putting it back in. This fixes http://llvm.org/bugs/show_bug.cgi?id=12321.
-----------------------

Any chance you could bump _LIBCPP_VERSION so that I can detect this? I'm currently doing a heinous "#define private protected" hack in my implementation file, and I'd prefer not to :slight_smile:

Michael

Hi All,

I've come across what I believe is a problem in libc++.

While working through Chris Kohlhoff's blog entries about system_error (Thinking Asynchronously in C++: System error support in C++0x - part 4) I discovered that it's not possible to inherit from std::error_category in libc++.

The following small test case compiles correctly under G++ 4.6.3 on Linux with libstdc++, but fails under Mac OS X Mountain Lion with Xcode 4.5 (Apple clang version 4.0 (tags/Apple/clang-421.0.60) (based on LLVM 3.1svn)).

#include <system_error>
#include <string>

namespace {
class test_category_impl
: public std::error_category
{
public:
virtual const char * name() const noexcept
{
    return "test_category";
}
virtual std::string message(int ev) const
{
    return "default";
}
};
}

const std::error_category & test_category()
{
static test_category_impl inst;
return inst;
}

With G++ on Linux I'm compiling with:
g++ -c -std=c++0x -o bugtest.o bugtest.cpp

This works as expected.

With clang on the Mac I'm compiling with:
clang++ -c -std=c++11 -stdlib=libc++ -o bugtest.o bugtest.cpp

This gives the following error:
$ clang++ -c -std=c++11 -stdlib=libc++ -o bugtest.o bugtest.cpp
bugtest.cpp:22:31: error: call to implicitly-deleted default constructor of '<anonymous>::test_category_impl'
static test_category_impl inst;
                          ^
bugtest.cpp:5:7: note: 'test_category_impl' defined here
class test_category_impl
  ^
1 error generated.

All literature I've come across indicates that I should be able to inherit from error_category and the wording in the draft of N3242 states "Classes may be derived from error_category to support categories of errors in addition to those defined in this International Standard." The libc++ implementation seems quite deliberate in its intent to not allow the user to inherit this class (it uses a private default constructor and a private friend class called __do_message internally within the library).

So have things changed? Are we no longer intended to be able to create error_category subclasses, or is this a bug?

This looks like a standards bug. I filed a LWG issue on it here:

http://cplusplus.github.com/LWG/lwg-active.html#2145

but the lwg has not yet commented on the issue. Generally my policy is to wait until the lwg addresses the issue before changing the libc++ implementation. But in this case I'm tempted to go ahead and fix this in anticipation of the lwg accepting the issue as proposed.

Does anyone have any /objections/ to me pushing this fix in now (as proposed in http://cplusplus.github.com/LWG/lwg-active.html#2145)?

Oh, never mind. It appears I *already* did that: :slight_smile:

-----------------------
r153194 | hhinnant | 2012-03-21 12:18:57 -0400 (Wed, 21 Mar 2012) | 1 line

It appears that the standard accidentally removed the default constructor for error_category. I'm putting it back in. This fixes http://llvm.org/bugs/show_bug.cgi?id=12321.
-----------------------

Any chance you could bump _LIBCPP_VERSION so that I can detect this? I'm currently doing a heinous "#define private protected" hack in my implementation file, and I'd prefer not to :slight_smile:

Done.

Howard