Compound literals in MSVC - c++

In GCC, I'm able to do this:
(CachedPath){ino}
inode->data = (struct Data)DATA_INIT;
where:
struct CachedPath
{
Ino ino;
};
typedef int8_t Depth;
struct Data
{
Offset size;
Blkno root;
Depth depth;
};
#define DATA_INIT {0, -1, 0}
MSVC gives the following error for these kind of casts:
error C2143: syntax error : missing ';' before '{'
How can I do this in MSVC? Further note that the code has been converted from C99, where I used designated initializers for this, and then cast it similarly. Any clarity on how these various features relate between C99, and MSVC/GCC implementations of C++ is appreciated.

The construct (Type){initialisers} is not a cast operation, but it is the syntactic construct of a compound literal.
This is a C99 construct, which GCC also supports in its C++ compiler as an extension. As far as I can determine, compound literals are not supported up to and including MSVC 2012, in either its C or C++ mode. The support in C mode was introduced later, in MSVC 2013. In C++ mode it is still not supported and I believe it is unlikely support will be added.
For MSVC 2012 and older, the alternatives for this construct are
Explicitly declare and initialise a temporary object of the desired struct type and use that instead of the compound literal in the assignment
Instead of doing a single assignment with the compound literal, use a separate assignment for each individual member.

MSVC is not conformant to C99 and only loosely conformant to previous versions of the C standard. I know no way to do what you want syntactically with MSVC, but the same effect can be obtained by using static const structs instead of anonymous compound literal constants, and local struct variables that are initialized with the correct values instead of anonymous compound literals that are nonconstant.
The idea behind this approach is that a C99 compound literal is (at least nearly) equivalent to a local variable of the same type at the same scope, initialized with the contents of the braces. Using static const structs in the case where the data is constant is just an optimization (it will likely produce smaller/faster code than the C99 compound literal approach).

Visual Studio, since VS2013, supports Compound literals and Designated initializers.
Which C99 features are available in the MS Visual Studio compiler?
Example:
// main.c
#include <stdio.h>
void func(int(*array)[3]);
int main()
{
// Designated initializers
int a[6] = { [4] = 29, [2] = 15 }; // [0, 0, 15, 0, 29, 0]
struct point { int x, y; };
struct point p = { .y = 13, .x = 27 }; // x = 27, y = 13
union foo { int i; double d; };
union foo f = { .d = 4 }; // d = 4.0
struct point ptarray[5] = { [2].y = 34, [2].x = 42, [0].x = 58 };
// (58 0), (0 0), (42 34), (0 0), (0 0)
// Compound literals
int *a1 = NULL;
a1 = (int[6]) { [4] = 29, [2] = 15 }; // [0, 0, 15, 0, 29, 0]
struct point p1;
p1 = (struct point) { .y = 13, .x = 27 }; // x = 27, y = 13
union foo f1;
f1 = (union foo) { .d = 4 }; // d = 4.0
struct point *ptarray1 = NULL;
ptarray1 = (struct point[5]) { [2].y = 34, [2].x = 42, [0].x = 58 };
// (58 0), (0 0), (42 34), (0 0), (0 0)
int *p2 = NULL;
p2 = (int[2]) { -1 };
p2 = (int[]) { -73, 89, 92 };
func(&(int[]) { -73, 89, 92 });
return 0;
}
void func(int(*array)[3])
{
for (int i = 0; i < 3; i++) {
printf("%d ", (*array)[i]);
}
}

MSVC is a mix of standards, and is not fully compliant with most of them, thus, you'll probably need to use a default initializer/constructor, like so (C++ way):
#define DATA_INIT 0,-1,0
inode->data = Data(DATA_INIT);
struct Data
{
Offset size;
Blkno root;
Depth depth;
Data(Offset size, Blkno root, Depth depth) : size(size), root(root), depth(depth)
{
}
};

Related

Why does deficit of element in an initializer not generate error [duplicate]

I am using an aggregate initializer to set up a block of static data for a unit test.
I would like to use the array size as the expected number of elements, but this can fail if too few initializers are provided:
my_struct_type expected[14] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
This gives no compiler error in Visual Studio 2008.
I would like to be able to use it as such:
const unsigned expected_size = sizeof(expected) / sizeof(my_struct_type);
BOOST_CHECK_EQUAL(points.size(), expected_size);
for( int i = 0; i < expected_size; i++ )
{
BOOST_CHECK_EQUAL(points[i].value, expected[i].value);
BOOST_CHECK_EQUAL(points[i].count, expected[i].count);
BOOST_CHECK_EQUAL(points[i].sym, expected[i].sym);
}
but because I don't have a compile-time guarantee of 14 points, this runs off the end of the array end of the provided values and into the default-initialized values.
Can I somehow enforce the number of aggregate array initializers at compile-time?
Actually it won't run off the end of the array, because the compiler will default-initialize all the elements of the array that you didn't initialize yourself.
If you're trying to make sure that you have a specific number of configured initializers, I'm not sure how to do that.
If you just want to make sure the array is the number of items you have:
my_struct_type expected[] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
Will do the trick. Then just use sizeof(expected) / sizeof(expected[0]) to get the total number of array elements.
First: There might be a warning for this. Have you tried compiling at the highest warning level?
Then: If you swap which value is calculated and which is literal, you could raise a compile-time error:
my_struct_type my_array[] = // <== note the empty []
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
BOOST_STATIC_ASSERT( sizeof(my_array)/sizeof(my_array[0]) == 14 );
Just for the sake of a non-Boost answer…
You can add an initialization requirement by modifying my_struct_type.
template< typename T >
struct must_be_initialized {
T value;
must_be_initialized( T const &v ) : value( v ) {}
// no default constructor!
operator T& () { return value; }
operator T const& () const { return value; }
};
struct my_struct_type {
must_be_initialized< double > f;
int i;
char c;
};
my_struct_type expected[14] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
// error: no default constructor exists
};
my_struct_type is still an aggregate, but it is not POD.
ISO/IEC 14882 (First edition 1998-09-01) in p. 8.5.1.7 states the following:
If there are fewer initializers in the
list than there are members in the
aggregate, then each member not
explicitly initialized shall be
default-initialized (8.5). [Example:
struct S { int a; char* b; int c; }; S
ss = { 1, "asdf" }; initializes ss.a
with 1, ss.b with "asdf", and ss.c
with the value of an expression of the
form int(), that is, 0. ]
Simply, the answer to your question is no.
According to the msdn, if fewer initializers are specified, the remaining elements are initialized with 0, so the code should work nonetheless.

Looking for Explanation of pointer initializing to const int and int

I was working through exercises in C++ Primer and found online solutions for Exercise 2.32.
I understood that the following code was illegal because initializing can't convert from int to int*:
int null = 0, *p = null;
However, two of the solutions that were mentioned, that I did not come up with were:
const int null3 = 0, *p3 = null3;
constexpr int null4 = 0, *p4 = null4;
How come it allows these during compile without error? I was still expecting the initialize of p3 and p4 to require the & to denote address (&null3, &null4).
Here is the code I have from my notepad file:
#include <iostream>
int main()
{
// int null = 0, *p = null; // it is not legal; depending on intent there are two ways to fix (that I can think off atm)
{
int null = 0, *p = &null; // if the goal is to point to 'null'
}
{
int null2 = 0, *p2 = 0; // if the goal is to create a nullptr
}
{
const int null3 = 0, *p3 = null3; // if the goal is to create a nullptr
}
{
constexpr int null4 = 0, *p4 = null4; // if the goal is to create a nullptr
}
return 0;
}
When I run via Microsoft Visual Studio CMDPrompt it allows me to 'cl "Exercise 2.32.cpp"' without error.
0 is one way of denoting a null pointer constant. (It's an integer type that evaluates to zero.) In other words it is a special case and you are allowed to assign a pointer type to it.
A standards compliant compiler should issue a diagnostic for the assignments of a pointer type to null3 and null4. (It should also issue a diagnostic for int *p = +0;.) If yours doesn't then check appropriate compiler flags are set.
Using nullptr is far better though:
int *p = nullptr;

C++ sub-object initialization

I'm porting some C code to C++ and I can't resolve a particular issue dealing with sub-object inititialization.
The following code is an example of what I mean :
#include <stdio.h>
#define MY_INDEX 1
#define MY_OTHER_INDEX 3
/* Structure declaration */
struct my_struct
{
int a;
int b;
int c;
};
/* Array declaration and initialization */
struct my_struct my_array[] =
{
[0] = (struct my_struct) {0, },
[MY_INDEX] = ((struct my_struct) {
.a = 10,
.b = 20,
.c = 30
}),
[MY_OTHER_INDEX] = ((struct my_struct) {
.a = 42,
.b = 42,
.c = 42
})
};
/** Test code */
int
main(void)
{
unsigned int i;
for (i = 0; i < sizeof(my_array)/sizeof(struct my_struct); i++)
printf("Index %u: a=%d, b=%d, c=%d\n",
i, my_array[i].a, my_array[i].b, my_array[i].c);
return 0;
}
It can be compiled without warnings nor errors with gcc -ansi -Wall, although adding the -pedantic flag will throw some warnings stating that ISO C90 forbids specifying subobject to initialize.
The initialization of my_array will act like if :
Index 0 will have a,b,c = 0
Index 1 (MY_INDEX) will have a=10, b=20, c=30
Index 2 will also have a,b,c = 0
Index 3 (MY_OTHER_INDEX) will have a,b,c = 42
I really like this form of initialization, I find it concise and readable.
Using this syntax with C++ will result in GCC thinking I'm declaring a lambda function because of the [], and even without the index GCC tells me it expected primary-expression before 'struct'.
What would be an equivalent in C++ (even with the C++11 standard) ? The key point is to be able to specify the structure fields name in the initializer for readability (the real structure have dozen of integer fields and bitfields), being able to also see the index in the initializer would be a plus too.
C++ doesn't have all the special aggregate initializer syntax that C supports. Instead, say this:
my_struct my_array[] = { { },
{ 10, 20, 30 },
{ 42, 42, 42 },
};
You can't have "gaps" in arrays (not even in C, I think).

C++ Class, Assigning values during Constructor initialization

I have a 2D array which I declared part of the classes private members. When I call the constructor, I start assigning values to the 2D array. But every time I do so, I'm hit with an error C2059. To make sure nothing else was causing that error I commented out that line and the compiler finished putting together a binary file.
tried:
Variable[row] = { 0, 1, 2, 3};
Variable[row][] = { 0, 1, 2, 3};
Variable[row][4] = { 0, 1, 2, 3};
No luck, any clues. Thanks in advance.
This syntax is only to be used for the creation of the object.
int array[4] = {1, 2, 3, 4};
Once the array is created, you have to use a loop to assign values to it.
Here's a short example :
class A
{
int array[4];
public:
A()
{
// Here, array is already created
// You can _assign_ values to it
}
};
If you want to give it values when it's instantiated in the constructor, the only way is to use initialization lists. Unfortunatly, you can't do this with a static array.
See this this thread.
Unfortunately, we can't yet properly initialize arrays that are members of classes. I don't know exactly how yours is declared, but here's an example of what to do:
class X
{
int Variable[3][4];
public:
X()
{
const int temp[][4] = { { 1, 2, 3, 4}, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
const int sz = sizeof(Variable)/sizeof(**Variable);
std::copy(*temp, (*temp) + sz, *Variable);
}
};
Since your question is not clear enough, all I can do is demonstrating a simple example.
2D array is initialized as,
//you may "optionally" provide the size of first dimension
int arr[][4] = {
{1,2,3,4},
{11,12,13,14},
{21,22,23,24}
};
And is acessed as,
for ( int i = 0 ; i < 3 ; ++i )
{
for ( int j = 0 ; j < 4 ; ++j )
{
cout << arr[i][j] << endl;
}
}
Online demonstration at ideone : http://www.ideone.com/KmwOg
Are you doing similarly?

Can I cause a compile error on "too few initializers"?

I am using an aggregate initializer to set up a block of static data for a unit test.
I would like to use the array size as the expected number of elements, but this can fail if too few initializers are provided:
my_struct_type expected[14] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
This gives no compiler error in Visual Studio 2008.
I would like to be able to use it as such:
const unsigned expected_size = sizeof(expected) / sizeof(my_struct_type);
BOOST_CHECK_EQUAL(points.size(), expected_size);
for( int i = 0; i < expected_size; i++ )
{
BOOST_CHECK_EQUAL(points[i].value, expected[i].value);
BOOST_CHECK_EQUAL(points[i].count, expected[i].count);
BOOST_CHECK_EQUAL(points[i].sym, expected[i].sym);
}
but because I don't have a compile-time guarantee of 14 points, this runs off the end of the array end of the provided values and into the default-initialized values.
Can I somehow enforce the number of aggregate array initializers at compile-time?
Actually it won't run off the end of the array, because the compiler will default-initialize all the elements of the array that you didn't initialize yourself.
If you're trying to make sure that you have a specific number of configured initializers, I'm not sure how to do that.
If you just want to make sure the array is the number of items you have:
my_struct_type expected[] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
Will do the trick. Then just use sizeof(expected) / sizeof(expected[0]) to get the total number of array elements.
First: There might be a warning for this. Have you tried compiling at the highest warning level?
Then: If you swap which value is calculated and which is literal, you could raise a compile-time error:
my_struct_type my_array[] = // <== note the empty []
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
BOOST_STATIC_ASSERT( sizeof(my_array)/sizeof(my_array[0]) == 14 );
Just for the sake of a non-Boost answer…
You can add an initialization requirement by modifying my_struct_type.
template< typename T >
struct must_be_initialized {
T value;
must_be_initialized( T const &v ) : value( v ) {}
// no default constructor!
operator T& () { return value; }
operator T const& () const { return value; }
};
struct my_struct_type {
must_be_initialized< double > f;
int i;
char c;
};
my_struct_type expected[14] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
// error: no default constructor exists
};
my_struct_type is still an aggregate, but it is not POD.
ISO/IEC 14882 (First edition 1998-09-01) in p. 8.5.1.7 states the following:
If there are fewer initializers in the
list than there are members in the
aggregate, then each member not
explicitly initialized shall be
default-initialized (8.5). [Example:
struct S { int a; char* b; int c; }; S
ss = { 1, "asdf" }; initializes ss.a
with 1, ss.b with "asdf", and ss.c
with the value of an expression of the
form int(), that is, 0. ]
Simply, the answer to your question is no.
According to the msdn, if fewer initializers are specified, the remaining elements are initialized with 0, so the code should work nonetheless.