5

The following code compiles successfully with both clang++ 3.8.0 and g++ 7.2.0 (compilation flags are -std=c++14 -Wall -Wextra -Werror -pedantic-errors):

struct Foo
{
    constexpr operator bool() const
    {
        return false;
    }
};


int main()
{
    constexpr bool b = Foo{};

    (void)b;
}

Is such behavior of the compilers standard compliant? Note that adding any member (like int i;) to the Foo class doesn't change anything.

2 Answers 2

4

Yes, the implicit constructor is constexpr this case. In general, it depends on the sub-objects.

[class.ctor]

A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (6.2) to create an object of its class type (4.5) or when it is explicitly defaulted after its first declaration. The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer (15.6.2) and an empty compound- statement. If that user-written default constructor would be ill-formed, the program is ill-formed. If that user-written default constructor would satisfy the requirements of a constexpr constructor (10.1.5), the implicitly-defined default constructor is constexpr. ... [snip]

Relevant requirements of a constexpr constructor:

[dcl.constexpr]

  • the class shall not have any virtual base classes;
  • for a non-delegating constructor, every constructor selected to initialize non-static data members and base class subobjects shall be a constexpr constructor;
Sign up to request clarification or add additional context in comments.

1 Comment

The implicitly-declared default constructor of Foo is indeed constexpr in OP's code, but that's irrelevant for the example as written, since Foo{} doesn't call any constructors; it's aggregate initialization. Neither would Foo() - that would be value-initialization that would perform zero-initialization, again without calling any constructors in the case of Foo. If a member int i; is added, as noted by the OP, the implicitly-declared default constructor is no longer constexpr (because it leaves i uninitialized), but everything else above still holds, so the code still works.
1

Yes it is. The default constructor that a compiler generates, and the trivial constructor

Foo() = default;

both enable you to write constexpr bool b = Foo{};, assuming all class members can be constructed constexpr. Note that if you had written

Foo(){}

then constexpr would not be allowed. (An important difference between default and a constructor provided with an empty body.)

2 Comments

Could you provide any reference to the text of the standard ?
See my comment to the other answer. Also note that a user-declared constexpr Foo() { } would be valid for the Foo in OP's code (no non-static data members), but not if we added a member int i; (it would still work for a member like int i = 0;).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.