http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47774

           Summary: [C++0x] constexpr specifier on ctor not ignored when
                    template instantiation causes ctor to not satify
                    constexpr requirements
           Product: gcc
           Version: 4.6.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: dev.li...@jessamine.co.uk


The definition of b in the program below fails to compile due to the default
constructor for its only member not being a valid constexpr.  B itself does not
claim to be a literal type or that instances of it should be usable as
constants but g++ currently seems to enforce the constexpr nature of the ctor
of X<T> even when T causes the definition to fail to meet the constexpr
constructor requirements.

7.1.5 para 4 states:

  6  If the instantiated template specialization of a constexpr
     function template or member function of a class template would
     fail to satisfy the requirements for a constexpr function or
     constexpr constructor, that specialization is not a constexpr
     function or constexpr constructor. [Note: if the function is
     a member function it will still be const as described below.
     Implementations are encouraged to issue a warning if a
     function is rendered not constexpr by a non-dependent
     construct.  --end note]

The program below demonstrates what I think to be non-compliance with this.  It
is a reduced case (I originally came across this when attempting to instantiate
a std::array<std::pair<F,S>,N> where objects of either F or S were not usable
as constants; pair's default constructor is specified as constexpr yielding the
same problem).

template <typename T>
struct X
{
   constexpr X() : t() {}
   T t;
};

struct CanBeCompileTimeConstant     { constexpr CanBeCompileTimeConstant() {}
};
struct CannotBeCompileTimeConstant  { CannotBeCompileTimeConstant() {} };

X<CanBeCompileTimeConstant> nonconstexpr1;
X<CannotBeCompileTimeConstant> nonconstexpr2;
constexpr X<CanBeCompileTimeConstant> constexpr1;
//constexpr X<CannotBeCompileTimeConstant> constexpr2; // fails as expected

struct A
{
   X<CanBeCompileTimeConstant> mem;
};

struct B
{
   X<CannotBeCompileTimeConstant> mem;
};

A a;
B b; // fails unexpectedly: 'constexpr X<T>::X() [with T =
CannotBeCompileTimeConstant]' is not 'constexpr'

Reply via email to