I have a simple struct:
struct Test
{
int a;
Test(int b, int c)
{
a = b * c;
}
};
I need to declare CT TransformData variable. It works with #define:
#define testDefault = Test(1, 2)
But I need to separate this variable to a separate namespace. If I use consexpr I get the error:
the type «const Test» of «constexpr» variable «test» is not literal
I've googled about constexpr and seems constexpr limits don't allow declare such class instance as constexpr.
Which are there ways to declare such constant?
The class you show is actually a good candidate for producing constexpr constants. But its constructor needs to be marked constexpr.
struct Test
{
int a;
constexpr Test(int b, int c)
: a(b*c) // must be initialized up to C++20
{
a = b * c + 1; // but can still be reassigned
}
};
A "literal type" is a normative term for types that can produce constant expressions. Your compiler was telling you that one of the requirements is missing.
Related
I am using g++4.8.0, which doesn't contain earlier constexpr bug. Thus below code works fine:
constexpr int size() { return 5; }
int array[size()];
int main () {}
However, if I enclose both the variable inside a class as static, then it gives compiler error:
struct X {
constexpr static int size() { return 5; }
static const int array[size()];
};
int main () {}
Here is the error:
error: size of array ‘array’ is not an integral constant-expression
Is it forbidden to use constexpr in such a way or yet another g++ bug?
Yes, it is ill-formed. Here's why:
A constexpr function needs to be defined (not just declared) before being used in a constant expression.
So for example:
constexpr int f(); // declare f
constexpr int x = f(); // use f - ILLEGAL, f not defined
constexpr int f() { return 5; } // define f, too late
function definitions inside a class specifier (as well as initializers and default parameters) are essentially parsed in an order like they were defined outside the class.
So this:
struct X {
constexpr static int size() { return 5; }
static const int array[size()];
};
Is parsed in this order:
struct X {
constexpr inline static int size(); // function body defered
static const int array[size()]; // <--- POINT A
};
constexpr inline int X::size() { return 5; }
That is, parsing of function bodies are defered until after the class specifier.
The purpose of this deferral of function body parsing is so that function bodies can forward reference class members not yet declared at that point, and also so they can use their own class as a complete type:
struct X
{
void f() { T t; /* OK */ }
typedef int T;
};
Compared to at namespace scope:
void f() { T t; /* error, T not declared */ }
typedef int T;
At POINT A, the compiler doesn't have the definition of size() yet, so it can't call it. For compile-time performance constexpr functions need to be defined ahead of their use in the translation unit before being called during compile, otherwise the compiler would have to make a multiple passes just to "link" constant expressions for evaluation.
Apparently it's not even a bug, because its status is RESOLVED INVALID, which means that the people behind GCC and that bugzilla, after reviewing the problem, don't think that this is a GCC bug.
I remind you on that page because there is also an answer for this behaviour in one of the related posts.
I just wanted to add that even though this may not be good practice and will restrict you to defining the class body in the same compilation unit that its declared, it's possible to force the compiler to compile the definition of the function bodies at the same point as its declaration by adding a redundant template parameter:
template <typename = void>
struct X {
constexpr static int size() { return 5; }
static const int array[size()];
};
int main()
{
X<> x{};
...
}
Consider the following example:
struct mystruct
{
int a;
int b;
int c;
};
int main()
{
mystruct x;
std :: cout << reinterpret_cast <size_t> (&(x.b)) - reinterpret_cast <size_t> (&x) << std :: endl;
}
What the above does is to use reinterpret_casts to determine the position of member b in memory within the struct mystruct. On my system (and, I guess, on any reasonable system) the above yields 4.
Now, what I would need is to do exactly the same, but at compile time. Is there a way to get such a thing done? What I need is some static constexpr size_t that at compile time will tell me what the position of b is within mystruct.
You can do that with offsetof macro:
size_t constexpr b_offset = offsetof(mystruct, b);
Note, that you cannot use offsetof outside of functions in the same class definition because this class is incomplete yet.
Background
What I'm trying to achieve: I'm trying to implement something like a Java enum (ie. enum that has some additional functionality). I came up with a solution using two classes, where one class represents a value and the other acts as an enumeration of possible values using static variables to represent each value. I want it to be a real replacement of enum, including the possibility to use the enum values in template instantiation. For this to work, an enum value needs to be a constant expression (constexpr). However, I'm not sure if I use the constexpr correctly.
The Code
Here is the code that I came up with:
class EnumType {
public:
enum Enum {val_A, val_B, val_C};
friend class EnumTypeList;
EnumType()
: m_ID(val_A), m_foo(0) {}
constexpr operator Enum() const {return m_ID;};
constexpr unsigned int getFoo() const {return m_foo;};
protected:
constexpr EnumType(const Enum v, const int foo)
: m_ID(v), m_foo(foo) {}
private:
Enum m_ID;
int m_foo;
};
class EnumTypeList {
public:
static constexpr EnumType A = EnumType(EnumType::val_A, 5);
static constexpr EnumType B = EnumType(EnumType::val_B, 4);
static constexpr EnumType C = EnumType(EnumType::val_C, 8);
};
The class EnumType holds the information of each value and provides some additional functions (here it is storing the additional value m_foo that can be accessed using getFoo() function). The enumeration itself is represented by the EnumTypeList that contains static constexpr variables, where each variable represents a possible value of an enum. This code allows me to use the variables from EnumTypeList in place of EnumType::Enum. Even in templates like in the following code:
template <EnumType::Enum T>
class Test {
public:
void test() {
std::cout << "Enum is not A" << std::endl;
}
};
template <>
class Test<EnumType::val_A> {
public:
void test() {
std::cout << "Enum is A" << std::endl;
}
};
int main() {
Test<EnumTypeList::A> a;
a.test();
Test<EnumTypeList::B> b;
b.test();
// this shouldn't compile
/*EnumType x = EnumTypeList::C;
Test<x> c;
c.test();*/
}
This works as I would expect – I can use the values from EnumTypeList in place of EnumType::Enum in template instantiation as demonstrated above, but I can't do it with EnumType x = EnumTypeList::C;
The Problem
While the code compiles correctly without any warning under gcc and clang, I'm not sure if I use the constexpr correctly. The thing is that while the EnumType constructor and the conversion operator operator Enum() are constexpr, they both access variables m_ID and m_foo that are not constant (because I need assignment operator).
This is fine, members of literal types are allowed to be modifiable.
In order to use the type in a constant expression you must construct it with constant arguments, but that's OK because you do that;
static constexpr EnumType A = EnumType(EnumType::val_A, 5);
The object constructed is a valid constant expression so can be used to initialize the constexpr variable A. You don't modify the members of the object, so it doesn't matter that they are modifiable.
Clang in particular is very strict about constant expressions, if you were doing something wrong it would give an error.
This object can be used where a constant expression is needed:
constexpr EnumType A5(EnumType::val_A, 5);
e.g.
constexpr int i = A5.getFoo();
This object cannot:
EnumType A6(EnumType::val_A, 6);
constexpr int i = A6.getFoo(); // error
How should I write a constructor for a class to initialize a member that is a const structure / has const fields?
In the following example, I define a constructor within structure B and it works fine to initialize it's const fields.
But when I try to use the same technique to initialize const fields of structure C within class A it doesn't work. Can someone please help me and rewrite my class A in a way, that it starts working?
#include <iostream>
class A
{
public:
struct C
{
C (const int _x) : x (_x) {}
const int x;
};
C c (3);
};
int main (int argc, char *argv[])
{
struct B
{
B (const int _x) : x (_x) {}
const int x;
};
B b (2);
std::cout << b.x << std::endl;
A a;
std::cout << a.c.x << std::endl;
return 0;
}
P.S.
I did some search and I think, I understand, that unless I have C++11 support or want to use boost library, I have to define a helper function to initialize a const struct within initialization list
(C++ Constant structure member initialization)
but it seems to be crazy that I have to define alike struct, but with non const fields to initialize a struct with const fields, doesn't it?
Another thing that I found tells that I should initialize const members in a constructor of the class A, rather than in a constructor of the struct C (C++ compile time error: expected identifier before numeric constant) but it also seems crazy to me, because why should I rewrite a class constructor every time I want to add a new struct, isn't it more convenient to have a separate constructor for each struct C within the class A?
I would be grateful to any comments that could possibly clarify my confusion.
I'd do the job like this:
#include <iostream>
class A {
public:
struct C {
C(const int _x) : x(_x) {}
const int x;
};
C c; // (3);
A() : c(3) {}
};
int main(int argc, char *argv []) {
A a;
std::cout << a.c.x << std::endl;
return 0;
}
Note that it's not a matter of using a ctor in A or in C, but of the ctor for A telling how the ctor for C should be invoked. If the value that will be passed will always be 3 that's not necessary, but I'm assuming you want to be a able to pass a value of your choice when you create the C object, and it will remain constant after that.
If the value will always be the same (3 in this case) you can simplify things a lot by also making the constant static:
struct A {
struct C {
static const int x = 3;
};
C c;
};
int main() {
A a;
std::cout << a.c.x << "\n";
}
So, if the value is identical for all instances of that class, make it static const, initialize it in place, and life is good. If the value is not known until you create an instance of the object, and remains constant thereafter for the life of that object, you need to pass it in through the constructors.
For a slightly different case, there's a third possibility: if C is an independent class (not nested inside of A) you might have a situation where other instances of C use various values, but all instances of C inside an A always use the same value. In this case, you'd do something like:
struct C {
const int x;
C(int x) : x(x) {}
};
struct A {
C c;
A() : c(3) {}
};
Of course, you can do the same thing when C is nested inside of A, but when/if you do, it generally means you're setting the same value for all instances of C, so you might as well use the static const approach instead. The obvious exception would be if A had multiple constructors, so (for example) A's default constructor passed one value for C::x and its copy constructor passed a different value.
There is this code:
namespace N {
struct B {
void f() {
i;
j;
}
int i;
};
int j;
}
int main() {
return 0;
}
Variable i is found but variable j is not. How does it work that variable in the class can be used before it is declared but the same does not work for namespace? How i is found - compiler parses first all class to find all members then bind it with references from member functions?
Indeed, the bodies of member functions (as well as variable initializers) are processed in a later phase than the class definition. You can check for yourself that the "declare before use" rule is still in full effect for class members, by trying to use members in other member declarations:
struct B
{
char c[sizeof i];
int i;
};
Demonstration: http://ideone.com/v1ksio
struct B2
{
decltype(i) f();
int i;
};
This also affects usage of the class itself which requires a complete type.
struct B
{
static char c[sizeof (B)];
};
Demonstration: http://ideone.com/Z9XOzm
But this is ok, because variable initializers are processed when the construction definitions are, where all members are known and the type is complete:
struct B
{
unsigned r{sizeof s};
unsigned s{sizeof (B)};
};