How to use C++ enums without getting a compiler warning - c++

I need to communicate that one and the same enum is passed to several calls. So I am doing this:
MiddleEarth::Creatures ally = MiddleEarth::Creatures::Elf;
myEnergy->Transfer(ally, 10);
myLives->Transfer(ally, 1);
Both Transfer methods are declared as follows:
Energy::Transfer(const Creatures& transferTo, (snip)
However, I am getting the following warning on the declaration of the variable named ally:
warning C4482: nonstandard extension used: enum 'MiddleEarth::Creatures' used in qualified name
What am I doing wrong? How do I rewrite my code so that it does not generate a compiler warning?

From the MSDN page on the warning;
When you refer to an enum inside a type, you do not need to specify the name of the enum.
int i = S::E::a; // C4482
int j = S::a; // OK
so in your case;
MiddleEarth::Creatures::Elf
should be
MiddleEarth::Elf

You probably want:
MiddleEarth::Creatures ally = MiddleEarth::Elf;

Related

Initialising variables in C++ with {}

I am using C++ in Visual Studio Code. When I want to initialise a variable I cannot initialise it with {} (e.g., int x {0};). Instead, I have to use () (e.g., int x (0);).
The error I get when using {} is "error: expected ';' at end of declaration" Although I have put ; at the end of declaration.
I'm using clang 11.0.0 as the compiler. Is it related to the compiler?
The code runs through the terminal by ./filename command. However, it gives errors when running by coderunner extension in VSCode.
In order to initialize a variable with {} you must say it is = {}.
Like this:
int x = {3}; //you wouldn't really do this for simple variable though I don't think since you can just say int x = 3;
//or if you are making a custom object you might say:
MyObject object = {"apples", 3, "red"};
// to set the variables inside the object. in the order they are declared.
I hope this answers your question!

Why doesn't C++ allow const after ::?

Folks,
Problem Statement - Does C++ allow a (static) const be limited to a class scope, so I can get rid of #defines that pollute entire namespace?
My observation is NO (in the following DIFFERENT examples), and I'd like to find out why and what's the best alternative. VS generates error C2589: 'const' : illegal token on right side of '::'
EXAMPLE1
// a.h
class A
{
…
..
static const uint_32 myConst = 1234;
};
//b.cpp
include “a.h”
…
B()
{
uint32_t arr[A::myConst]; // C2589! const : illegal token on right side of '::'
}
EXAMPLE 2
// a.h
class A
{
…
..
enum blah
{
...
myConst = 1234,
..
};
};
//b.cpp
include “a.h”
...
B()
{
uint32_t arr[A::myConst]; // C2589! const : illegal token on right side of '::'
}
When you take your macro:
#define CONST 1234
and substitute it for where you use it:
static const int CONST = 1234;
The end result is nonsense:
static const int 1234 = 1234;
In another instance:
Int a1[a::CONST];
This also becomes nonsense:
Int a1[a::1234];
This all begs the question, what are you trying to do?
It looks like you're trying to create a member variable with the same name as your macro, CONST, here:
class A
{
static const int CONST = 1234;
};
However since when this code is compiled the macro has already been defined, the preprocessor changes this by substituting the macro before the compiler itself can get a crack at it. By the time the code is compiled, it looks like this:
class A
{
static const int 1234 = 1234;
};
Best is to just do away with the macro entirely, and then retrofit your code to use proper constants like you're trying to do here. Don't mix and match. At the very least, don't use the same name for the member as you do for the macro.
First of all your class is called A, as in capital A, not a. The class name is used to qualify the constant you are trying to use. So, change your code to use A::CONST. By the way, this is C++ not C# or Java, so there is no such thing as an Int, unless for some bizarre reason you decided to invent your own integer type.
As an aside, using all caps to name constants can collide with macros and is a good way to get into trouble, especially since pre-processing happens first and macros are substituted for all cases of the constants. This can often lead to invalid C++ code with syntax errors that are difficult to understand. That's why you should never use all caps to name constants, since this is a convention most commonly used for macros.
If I may make a guess, it looks like you're trying to use :: the same way you use . in Python.
It looks like you really don't understand what the scope resolution operator does, or how it works.
:: has a very specific, and quite limited usage. Until you understand it better, we're going to have a really hard time helping you.

Would the following code causing problems in C++?

I saw someone writing code like this , in a C++ class:
int foo ( int dummy )
{
this->dummy = dummy;
}
Shall we use code like that , will it cause problems ?
I tried to compile something like this , it seems to be worked.
#update:
I posted this mostly about the name dummy , and the internal variable this->dummy , and if it's problem causing
That's perfectly fine for a member function, other than you're missing a return statement. dummy will shadow the member variable and so you use this-> to refer to member.
int foo ( int dummy )
{
this->dummy = dummy; // set member to argument
return this->dummy;
}
Don't do this for things more complex than a simple set function, as it's confusing.
int foo ( int dummy ) // Bad practise! Rename this param as the function isn't a setter
{
this->dummy = dummy * 2 + 1;
return this->dummy;
}
There is nothing wrong with doing that perse. It can get confusing though if you use dummy assuming it is coming from the class but its actually coming from the parameter.
IMO, its better to use something to denote it is a class member. Some people use simply mDummy, other m_Dummy, others just write dummy_.
Its up to you what you prefer but most of all you should be consistent.
The code is not fine. The function is defined as returning an int but there is no return statement. The compiler might only give a warning about this, but the function calling foo might expect it to return a valid value, which it doesn't, and bad stuff might happen.
You have to do it this way if you're passing a parameter with the same name as the member variable.
But it might be a better practice to avoid a hidden (member-)variable by using different names. There's different coding styles, some would use dummy_, some would use mDummy or other ways to name member variables. This makes your code less confusing.
Well there is nothing wrong with your use, but the code needs to return an int as its an int function :)
Dummy variable in your current class is assigned to the passed int, however do remember they are different but now pointing to the same thing, therefore its better to give it a different name as its in a different.
You could however loose precision under certain variable types.
#include <stddef.h>
typedef struct intlist {
int size;
int i[1];
} intlist;
intlist *
makeintlist (int size)
{
intlist *ilp = malloc (offsetof (intlist, i[size])); /* not C++ */
ilp->size = size;
return ilp;
}
member variable size is allocated to size
That will work.
Don't do it, it's confusing!

How should I properly initialize a C struct from C++?

I have the following code in a C++ file:
#include <sys/socket.h>
// ...
void someFunc() {
struct msghdr msg = {0}; // <<< Uninitialized member here
}
When I compile with g++ using -Wall -Wextra, I get warnings:
error: missing initializer for member 'msghdr::msg_namelen'
...same for several other fields
My problem is this: I can't explicitly initialize all the fields, because I don't know what fields will exist (cross-platform) in a struct msghdr. The struct doesn't have a default constructor, since it's a C struct. I was under the impression that the = {0} form led to zero-initialization of all fields (which would be fine for me), but the g++ error message suggests not.
What are my options here?
Do this:
void someFunc()
{
msghdr msg = {}; // <<< All members zero-initialized
}
The g++ -Wextra warning level is IMHO not very useful.
The code that you have is also formally OK for a "C struct", in standardeese known as POD (plain old data structure). But your code explicitly initializes the first member with 0. That won't necessarily work for an aggregate that isn't POD, e.g., with a std::string as the first member, while the pure {} will work also for that.
In passing, often a POD like the one you're dealing with has a byte count as the first member, and then you can do like …
void foo()
{
SomePODStruct o = {sizeof(o)}; // The other members zero-initialized.
}
Perhaps add a STATIC_ASSERT that the byte count member is first (at offset 0).
This should work:
memset(&msg, 0, sizeof(msg));
The specific warning flag that causes this is -Wmissing-field-initializers, which is turned on as part of -Wextra. The simplest way to avoid this (bogus) warning is therefore to use -Wno-missing-field-initializers.
If you can't live with the warning and/or don't want to disable the warning, then I think it will have to be explicit initialisation via e.g. memset:
memset(&msg, 0, sizeof(msg));

regarding encryption method

i am using encrypt function of cryptography api(fun declared as virtual)
//fun declaration
TBool EncryptL(const TDesC8 &aInput, TDes8 &aOutput);
//function calling
TBuf8<10> text;
TBuf8<10> cipher;
text.Copy(_L("Hello"));
iEncryptor.EncryptL(text,cipher); it shows error expression syntax error
//fun definition
TBool CRSAAlgo::EncryptL(const TDesC8 &aInput,TDes8 &aOutput)
{
if(iEncryptor)
{
TInt len = iEncryptor->MaxInputLength();
}
}
i want to know what is exact problem
The main issue here, the reason your compiler complains is that you are using iEncryptor as an object or a reference, while it probably is a C++ pointer.
To move to the next stage, try using:
iEncryptor->EncryptL(text,cipher);
As you did not post the exact error message you get from the compiler I have to guess.
I assume the problem is that the EncryptL function you show expects to get arguments of type TDesC8 and you pass a TBuf8<10> to it. Unless TDesC8 were a typedef to TBuf8<10> these are different and therefore for the compiler incompatible types.
Ypou are also using iEncryptor once as a pointer: iEncryptor->MaxInputLength(); and at the location where you see the error as an object: iEncryptor.EncryptL(text,cipher);. Only one form can be correct. As we don't have more code from you I don't know which, but given the fact that the latter has the error I suspect the latter.