Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent default initialization of a const variable with a class type

I have a custom class that I want to behave like a built-in type.

However I have noticed that you can initialise a const variable of that class without providing an initial value. My class currently has an empty default constructor.

Here is a comparison of int and my class foo:

int a;              // Valid
int a = 1;          // Valid
const int a = 1;    // Valid
const int a;        // Error

foo a;              // Valid
foo a = 1;          // Valid
const foo a = 1;    // Valid
const foo a;        // Should cause an error, but it compiles

As you can see I need to prevent

const foo a;

from compiling.

Any ideas from C++ gurus?

like image 565
ljbade Avatar asked Nov 18 '11 12:11

ljbade


2 Answers

It compiles only if it has a default constructor, and it compiles because it has it, which means that it is initialized. If you don't want that line to compile, just disable the default constructor (will also make foo a; an error as an unwanted side effect). Without a definition of foo or what you want to do, this is as far as I can get.

I don't think there is any way of achieving what you want (i.e. allow the non-const variable to be default initialized, while having the const version fail compilation and allowing the other use cases --that require providing constructors)

like image 55
David Rodríguez - dribeas Avatar answered Nov 14 '22 23:11

David Rodríguez - dribeas


The rules of C++ simply say that default-initialization (e.g. new T;) and value-initialization (e.g. new T();) are the same for objects of class type, but not for objects of fundamental type.

There's nothing you can do to "override" this distinction. It's a fundamental part of the grammar. If your class is value-initializable, then it is also default-initializable.

There is a sort-of exception for classes without any user-defined constructors: In that case, initialization of members is done recursively (so if you default-init the object, it tries to default-init all members), and this will fail if any of the class members are themselves fundamental, or again of this nature.

For example, consider the following two classes:

struct Foo { int a; int b; };
struct Goo { int a; int b; Goo(){} };

//const Foo x; // error
const Goo y;   // OK

The implicit constructor for Foo is rejected because it doesn't initialize the fundamental members. However, y is happily default-initialized, and y.a and y.b are now "intentionally left blank".

But unless your class doesn't have any user-defined constructors, this information won't help you. You cannot "forward" the initialization type to a member (like Foo() : INIT_SAME_AS_SELF(a), b() { }).

like image 41
Kerrek SB Avatar answered Nov 15 '22 00:11

Kerrek SB