15786

Constexpr class: Inheritance?

Question:

First of all, I'm working with Clang 3.4.1

I'm writting a global variable which has to serve as a placeholder on compile-time contexts (Primarily as value template parameter). For that purpose, I have written a constexpr class named chameleon (It mimics the behaviour of any runtime value):

struct chameleon { template<typename T> constexpr operator T() const { return T{}; } constexpr chameleon() = default; };

Since both the conversion operator and the constructor are specified as constexpr, I'm able to make instances of that class at compile-time. <a href="https://ideone.com/KhAN6R" rel="nofollow">For example</a>:

template<int foo> struct bar {}; using mytype = bar<chameleon{}>;

Since this works, and I use it in other places, I decided to write such placeholder type just inheriting from chameleon:

template<std::size_t I> struct placeholder : public chameleon { using chameleon::chameleon; };

I'm using C++11, so I just used the "new" (C++11 has three years...) inheriting constructors feature.

When declaring the placeholder variable:

constexpr const placeholder<0> _1;

The compiler rejects the code saying it expects an user-defined default ctor for initialization. So <em>"Well, inheriting ctors doesn't propagate constexpr, or something like that"</em> is what I though. Then I changed the using to a default ctor declaration:

template<std::size_t I> struct placeholder : public chameleon { constexpr placeholder() = default; };

Now the compiler says:

<blockquote>

error: default initialization of an object of const type 'const placeholder<0>' requires a user-provided default constructor

</blockquote>

If I change the = default to a manually defined empty constructor (constexpr placeholder() {}) then it works, but the constructor is not evaluated as constexpr and the usage of the _ placeholder in compile-time contexts is invalid (The common is not a constant expression error). The same for manually calling the base ctor.

My question is: <strong>Whats wrong with inheritance and constexprconstructors? Is there any way to use inheritance when writting constexpr classes?</strong>

<strong>EDIT:</strong> I have a division-by-zero bug, the code using the manually written ctor works perfectly. On the other hand, I don't understand why neither the inheriting constructor or the default constructor declaration worked. The question remains there.

Answer1:

<blockquote>

So "Well, inheriting ctors doesn't propagate constexpr, or something like that" is what I thought

</blockquote>

That's not the issue; default and copy/move constructors cannot be inherited. If you don't explicitly define or default them, they'll be implicitly defined following the usual rules.

<em>§12.9 [class.inhctor]</em>

<blockquote>

3      For each non-template constructor in the candidate set of inherited constructors <strong>other than a constructor having no parameters or a copy/move constructor having a single parameter</strong>, a constructor is implicitly declared with the same constructor characteristics unless there is a user-declared constructor with the same signature in the complete class where the <em>using-declaration</em> appears or the constructor would be a default, copy, or move constructor for that class. ...

5      [ <em>Note:</em> Default and copy/move constructors may be implicitly declared as specified in 12.1 and 12.8. <em>—end note</em> ]

</blockquote>

Consequently, placeholder, with or without the using declaration for inheriting chameleon's constructors, will have a default constructor implicitly defined, and this constructor will be constexpr.

<em>§12.1/5 [class.ctor]</em>

<blockquote>

... If that user-written default constructor would satisfy the requirements of a constexpr constructor (7.1.5), the implicitly-defined default constructor is constexpr. ...

</blockquote>

Your class, with a user provided default constructor, satisfies the requirements in §7.1.5/4 for a constexpr constructor. The error you saw was because of the next part.

<hr />

As for why you must provide a constructor definition for a const object, let's take a look at your class.

struct chameleon { template<typename T> constexpr operator T() const { return T{}; } constexpr chameleon() = default; };

This class is both trivial (9/6) and standard layout (9/7), hence it is a POD (9/10). A POD is uninitialized by default, so a const POD without an initializer would be uninitialized, and immutable, making it pretty much worthless (or I'm not able to think of any use cases, at least).

By providing a default constructor, the class is no longer a POD, and will be default initialized.

As @Casey points out in the <a href="https://stackoverflow.com/questions/24333458/constexpr-class-inheritance#comment37616985_24333884" rel="nofollow">comments</a>, this requirement is listed in §8.5/7

<blockquote>

If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.

</blockquote>

Recommend

  • Why does an n instead of b or d or nothing change the behaviour of sed in this script?
  • Setting up SSH on sourcetree - wont PUSH to GitLab - asks for password
  • What is SRV in MS RPC and what should I know about it?
  • ReactJS- remove HTTP header before redirect
  • Spark DataFrame equivalent to Pandas Dataframe `.iloc()` method?
  • Is it possible to refresh a div on a radio button click?
  • undefined method `posts_path' for #
  • declaring device constant in terms of another constant
  • Set up the Android-Facebook sdk for Netbeans
  • What is #:: method
  • Strange multiple assignment error in C++
  • FParsec: how to combine parsers so that they will be matched in arbitrary order
  • Sharing Redis settings across routes
  • Calling right overload of the java method from jython
  • Why is new Number(8) not exactly equal to 8?
  • Why does NotifyIcon not set SynchronizationContext?
  • PhpStorm: annotation for inherited method return type?
  • Two columns in subquery in where clause
  • How to initialize context? [closed]
  • Validation fired but Red Border does not appear with User Control in Silverlight 4
  • custom string delimiters stringtemplate-4
  • What is this strange character in chrome's resource css viewer?
  • SQL: Getting the physical size of a subset of a table
  • Should I or shouldn't I use the CachingConnectionFactory with hornetq 2.4.1
  • Does it make sense to call System.gc() and Thread.sleep() when working on Bitmaps?
  • Jackson Parser: ignore deserializing for type mismatch
  • Abort upload large uploads after reading headers
  • C++ and preprocessor macros: variadic type
  • java.lang.NoClassDefFoundError: com.parse.Parse$Configuration$Builder on below Lollipop versions
  • What is Eclipse's Declaration View used for?
  • Statically linking a C++ library to a C# process using CLI or any other way
  • Calling of Constructors in a Java
  • Acquiring multiple attributes from .xml file in c#
  • C# - Getting references of reference
  • -fvisibility=hidden not passed by compiler for Debug builds
  • how does django model after text[] in postgresql [duplicate]
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • How can I remove ASP.NET Designer.cs files?
  • Are Kotlin's Float, Int etc optimised to built-in types in the JVM? [duplicate]
  • java string with new operator and a literal