Porting structs to MSVC 2017 - c++

how can I port the following Linux declaration to MSVC? "Expected identifier" is what I get as an error.
static const struct tap_align_size align_size_000000_00[] = {
[0] = {.align = 1,.size = 4, },
[52] = {.align = 1,.size = 4, },
};
where
struct tap_align_size {
uint8_t align:4, size:4;
};

You would have to make a struct with a constructor (with an array within) or laboriously type {} 51 times. The latter possibility is more risky because you do not know the order of fields in the struct, and even if you knew, a newer version could shuffle them, with the compiler unable to detect the change.

Related

Why is my static array[] of my classes failing

I can certainly solve this half a dozen ways but I am curious why what I have coded is not working. (VS 2010 Pro C++)
I have a small class
class Protocol_element
{
public:
const char *Argument;
int EnumID;
int TrueEnum;
int FalseEnum;
bool IsEnabled;
...
It has an explicit ctor:
Protocol_element(const char * arg, int id, int tru, int fals, bool isEnab)
{
Argument = arg;
EnumID = id;
TrueEnum = tru;
FalseEnum = fals;
IsEnabled = isEnab;
{
Then I have an array of addresses of these class elements that is declared static
Protocol_element *Parms::Protocol[] = {
&Protocol_element("SSLV2", GSK_PROTOCOL_SSLV2, GSK_PROTOCOL_SSLV2_ON, GSK_PROTOCOL_SSLV2_OFF, true),
&Protocol_element("SSLV3", GSK_PROTOCOL_SSLV3, GSK_PROTOCOL_SSLV3_ON, GSK_PROTOCOL_SSLV3_OFF, true),
&Protocol_element("TLSV1", GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_ON, GSK_PROTOCOL_TLSV1_OFF, true),
&Protocol_element("TLSV1.1", GSK_PROTOCOL_TLSV1_1, GSK_PROTOCOL_TLSV1_1_ON, GSK_PROTOCOL_TLSV1_1_OFF, false),
&Protocol_element("TLSV1.2", GSK_PROTOCOL_TLSV1_2, GSK_PROTOCOL_TLSV1_2_ON, GSK_PROTOCOL_TLSV1_2_OFF, false),
&Protocol_element("TLSV1.3", GSK_PROTOCOL_TLSV1_3, GSK_PROTOCOL_TLSV1_3_ON, GSK_PROTOCOL_TLSV1_3_OFF, false),
nullptr
};
I can trace with the debugger through the constructors. I can see my whole array get built just as I would expect. But if I breakpoint on int main() the array now is uninitialized storage.
Why? Why did my array "disappear"?
Okay, thanks. I was not sure, but when it compiled, I expected that it might work. As I said, I can think of a dozen ways to solve the problem, and what I have done now, and works, is
Protocol_element Parms::Protocol[] = {
{ "SSLV2", GSK_PROTOCOL_SSLV2, GSK_PROTOCOL_SSLV2_ON, GSK_PROTOCOL_SSLV2_OFF, true },
{ "SSLV3", GSK_PROTOCOL_SSLV3, GSK_PROTOCOL_SSLV3_ON, GSK_PROTOCOL_SSLV3_OFF, true },
{ "TLSV1", GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_ON, GSK_PROTOCOL_TLSV1_OFF, true }, // TODO: Document
{ "TLSV1.1", GSK_PROTOCOL_TLSV1_1, GSK_PROTOCOL_TLSV1_1_ON, GSK_PROTOCOL_TLSV1_1_OFF, false },
{ "TLSV1.2", GSK_PROTOCOL_TLSV1_2, GSK_PROTOCOL_TLSV1_2_ON, GSK_PROTOCOL_TLSV1_2_OFF, false },
{ "TLSV1.3", GSK_PROTOCOL_TLSV1_3, GSK_PROTOCOL_TLSV1_3_ON, GSK_PROTOCOL_TLSV1_3_OFF, false },
nullptr
};
The program is invalid. The address-of operator requires an lvalue.
You are however using a non-standard language extension of a very buggy and outdated compiler. This extension prevents the compiler from yelling at you and refusing to compile the program like the standard (any year) requires. Unfortunately it does not cause the compiler to emit meaningful code. So garbage in, garbage out.
You should upgrade to the latest version of MSVC and use the latest standard (the /std:c++latest flag), or at the very least disable the non-standard extensions with the /Za flag. I cannot guarantee it will help specifically with VS 2010 though, but it does help with modern versions of MSVC.

Statically initialize nested C++ structures with named labels using g++

I am importing/porting existing C code to C++. I am hoping to make as few changes to the existing body of code as possible to minimize preterbing the existing code.
This code makes use of static named initialization of nested structures. For quick made up example:
Car car =
{
.color = RED,
.tire.tread = OLD,
.tire.diameter = 27.106,
.tire.material.type = RUBBER,
.tire.material.density = 700,
};
I figured out that these are called designated initializers.
I learned about GNU initializers but I haven't figured out how to implement hierarchy with it.
I read that designated initializers are supported in g++ with c++11 enabled, but that didn't seem to work for me.
The code I am porting has pages of initialization with at least four layers deep of hierarchy. So I am trying to look for a straightforward transformation which doesn't get too involved.
I am looking for one of these possible solutions:
How to enable C99 designated initializers
How to formulate hierarchical GNU style initialization
What is a C++ equivalent way to do this which wouldn't be error prone transcribing war and peace.
An obvious solution I haven't thought of
I am using g++ version
g++.exe (i686-posix-dwarf-rev0, Built by MinGW-W64 project) 8.1.0
The use of such nested designated initializers seems to be something of an edge case. The following works in both clang-cl (in Visual Studio 2019) and the native MSVC compiler (but the latter only with the /std:c++latest option, which uses the draft C++20 standard):
struct inner {
int x, y;
double z;
};
struct outer {
char a;
double b;
inner c;
};
outer my_outer = { .a = 'a', .b = 1.2, .c = { .x = 3, .y = 4, .z = 5.6 } };
With clang-cl, the initializer can be abbreviated to the following form:
outer my_outer = { .a = 'a', .b = 1.2, .c.x = 3, .c.y = 4, .c.z = 5.6 };
but MSVC complains in this case, with:
error C7558: nested member access is not allowed in standard C++
designated initializers; use a nested initializer list
So, for your example, you could try this:
Car car =
{
.color = RED,
.tire = {
.tread = OLD,
.diameter = 27.106,
.material.type = RUBBER,
.material.density = 700,
}
};
There's a helpful 'discussion' of the topic on cppreference, with this part being notable:
...each designator must name a direct non-static data member of T, and
all designators used in the expression must appear in the same order
as the data members of T.

C++ enum definitions not being accepted

I would like to use some nss3.dll code in my program. To do this I decided to declare all of the compound datatypes that it needs and call the functions inside the dll file with them.
I am using a file in the firefox source code to see how to properly use the functions I need. In one of the functions it declares one of these compound datatypes (secuPWData) and passes it variables. Here is the definition I pasted into my code without any errors:
typedef struct {
enum {
PW_NONE = 0,
PW_FROMFILE = 1,
PW_PLAINTEXT = 2,
PW_EXTERNAL = 3
} source;
char *data;
} secuPWData;
The declaration of this struct looks like this in the code I'm looking at: secuPWData pwdata = { PW_NONE, NULL };
When I try to use a similar (or even the same) declaration, it complains about the PW_NONE attribute, claiming it is undefined. When I tried to pass in the 0 value in its place, it told me that 'a value of type "int" cannot be used to initialize an entity of type "enum secuPWData::"'. To try to debug the issue, I tried pasting the definition right on top of the declaration, without any change.
What is causing this problem to occur?
Thanks for any help.
just as #n.m. mentioned try using secuPWData::PW_NONE
#include <iostream>
using namespace std;
typedef struct {
enum {
PW_NONE = 0,
PW_FROMFILE = 1,
PW_PLAINTEXT = 2,
PW_EXTERNAL = 3
} source;
char *data;
} secuPWData;
int main() {
secuPWData pwdata = { secuPWData::PW_NONE, NULL };
return 0;
}
worked for me .. ideone - link

c2797 List initialization inside member initializer list or non static data member initializer not implemented

I m getting the following error in visual studio 2013 when i try to compile my project.
c2797:List initialization inside member initializer list or non static data member initializer not implemented.
Here is the piece of code for which it is throwing the above compiler error.
====sample.h====
enum class Process
{
TUNNEL_IP_VERSION, // Tunnel::IPVersion::Type
PADDING_BYTE,
IP_ADDRESS_FIT_ACTUAL_SIZE,
IP_ADDRESS_FIT_IPv6_SIZE,
PORT_NUMBER,
};
using ProcessingOrder = std::vector<Process>;
const ProcessingOrder m_ProcessingOrder =
{
Process::TUNNEL_IP_VERSION,
Process::PADDING_BYTE,
Process::IP_ADDRESS_FIT_IPv6_SIZE,
Process::PORT_NUMBER
};
Eventhough VS2013 supports c++11 feature - intialize list , why it is throughing the above error !? How to get off with this situation? What do i need to change in the code to fix this?
Thanks for your answer. That works great.
I have a similar situation for the below statement as well.
m_Attribute{SSL_CTX_new(g_SSLChoice[version].m_pfSSLMethod()), 0, 0}
{
where,
m_Attribute is,
struct{
SSL_CTX* const m_pContext;
Socket* m_pSocket;
X509* m_pCertificate;
}m_Attribute;
SSL_CTX_new, is a standard definition in ssl.have
g_SSLChoice is,
g_SSLChoice[CloudSSL::TLSv1_2 + 1] =
{
/* [SSLv23] = */ {&SSLv3_client_method, 0},
/* [SSLv3] = */ {&SSLv23_client_method, SSL_OP_NO_SSLv2},
/* [TLSv1] = */ {&TLSv1_client_method, SSL_OP_NO_SSLv3},
/* [TLSv1_1] = */ {&TLSv1_1_client_method, SSL_OP_NO_TLSv1},
/* [TLSv1_2] = */ {&TLSv1_2_client_method, SSL_OP_NO_TLSv1_1}
};
in which,
class CloudSSL : public Util::Thread
{
public: enum Version
{
// SSLv2, // Not supported
SSLv23,
SSLv3,
TLSv1,
TLSv1_1,
TLSv1_2
};
And finally m_pfSSLMethod is,
const SSL_METHOD* (*m_pfSSLMethod)();
Visual Studio did not implement this feature yet. An workaround can be found here
You can just use
const ProcessingOrder m_ProcessingOrder = ProcessingOrder
{
Process::TUNNEL_IP_VERSION,
Process::PADDING_BYTE,
Process::IP_ADDRESS_FIT_IPv6_SIZE,
Process::PORT_NUMBER
};
For your second case.
struct Attribute_t{
SSL_CTX* const m_pContext;
Socket* m_pSocket;
X509* m_pCertificate;
}m_Attribute;
then just
m_Attribute = Attribute_t{SSL_CTX_new(g_SSLChoice[version].m_pfSSLMethod()),
0, 0}

Union initialisation in a struct

I've been browsing stackoverflow concerning the problem of initialising a union in a struct but I didn't manage to get it right.
Here is my struct
typedef struct dc_netif_filter {
unsigned char filter_type;
union {
uint32_t itf_nb;
char * buf;
} value;
} dc_netif_filter_t;
In my code, i have tried to use :
dc_netif_filter_t netif = {DC_NETIF_SELECT_NAME,{{0, "tun"}}};
which gives error: braces around scalar initializer for type ‘uint32_t’
and
dc_netif_filter_t netif = {DC_NETIF_SELECT_NAME,{0, "tun"}};
which gives error: too many initializers for ‘dc_netif_filter::< anonymous union>’
How do i declare such a dc_netif_filter_t ?
I'm using g++ on ubuntu. Note that the dc_netif_filter_t isn't a struct that I can modify as it comes from a third party project.
**EDIT : as I've been explained, i can only initialise one field. The problem is that with
dc_netif_filter_t netif = {DC_NETIF_SELECT_NAME,"tun0"};
I get a conversion error : invalid conversion from ‘const char*’ to ‘uint32_t
Thanks
As the compiler says, too many initializers for ‘dc_netif_filter::< anonymous union>’.
Initialize only one field, not both.
Use the name of the field to initialize it properly:
dc_netif_filter_t netif = {DC_NETIF_SELECT_NAME, { buf: "tun0" }};
It looks like you are trying to initialize your structure to indicate that the buf member is to be used, and that the value of that buf should be "tun". Since C++ before C++11 lacks designated initializers, you cannot do it with an initializer: only the first field of the union can be initialized, so you need to do your assignment in code:
static get_dc_netif_filter_t() {
static c_netif_filter_t netif = {DC_NETIF_SELECT_NAME, {0}};
if (netif.value.itf_nb == 0) {
netif.value.buf = "tun";
}
return netif;
}
C++11 lets you do it like this:
dc_netif_filter_t netif = {DC_NETIF_SELECT_NAME, { .buf = "tun"}};
This works under g++ 4.7.0:
dc_netif_filter_t netif = {DC_NETIF_SELECT_NAME, {.buf="tun"}};
Although designated initializers are supposed to be C only, not C++! Maybe it's a GNU extension?
I guess the best (most compatible) way is to assign the members after initialization:
dc_netif_filter_t netif;
netif.itf_nb = DC_NETIF_SELECT_NAME;
netif.value.buf = "TUN";