How do you handle "warning #370-D: class "match_str" defines no constructor" - c++03

The following structure:
struct match_str {
const char* s; // Pointer to string
const uint8_t l; // Length
};
Is intended to be initialized only as follows:
const match_str s = {"200 OK", 5};
and used as normal struct with constant members. During compilation time, I get the following warning:
warning #370-D: class "match_str" defines no constructor to initialize the following: const member "match_str::l"
What can I do with the warning? I get the warning, it makes sense, but I am not sure how to handle it. Basically, this is a safer c-string structure that I use in my code, and each instance is hand written like the const char*
Reference:
Is this warning alright - "#368-D: <entity> defines no constructor to initialize the following:"?
warning #411: class foo defines no constructor to initialize the following:

Just get rid of the const in the struct, and make the instances of the struct const, which will serve the purpose of keeping members constant.

Related

Kotlin Native Initialize Array of Struct

In Kotlin/Native, what is the correct way to create and initialize an array of a structure? My code interfaces with a C library that defines the relevant structures as:
typedef struct VkDeviceQueueCreateInfo {
...
} VkDeviceQueueCreateInfo;
typedef struct VkDeviceCreateInfo {
...
uint32_t queueCreateInfoCount;
const VkDeviceQueueCreateInfo* pQueueCreateInfos;
...
} VkDeviceCreateInfo;
I've created wrapper classes DeviceQueueCreateInfo and DeviceCreateInfo. The Kotlin bindings are generated as classes inheriting from CStructVar and used like this:
class DeviceQueueCreateInfo(...) {
// Allocates in `scope` and fills a `VkDeviceQueueCreateInfo`
fun toRaw(scope: MemScope): VkDeviceQueueCreateInfo = ...
}
class DeviceCreateInfo(val queueCreateInfos: List<DeviceQueueCreateInfo>) {
// Allocates in `scope` and fills a `VkDeviceCreateInfo`
fun toRaw(scope: MemScope) = with(scope) {
alloc<VkDeviceCreateInfo>().also {
it.queueCreateInfoCount = queueCreateInfos.size.toUInt()
it.pQueueCreateInfos = ??? // Allocate array of struct in `scope`
}
}
}
I've added a ??? to the code to show where I'm having trouble. Kotlin NativePlacement has allocArray<T>(length: Int), so that was obviously my first stop:
it.pQueueCreateInfos = allocArray(queueCreateInfos.size)
And then to initialize them I tried:
it.pQueueCreateInfos = allocArray<VkDeviceQueueCreateInfo>(queueCreateInfos.size)
.also { arr ->
queueCreateInfos.forEachIndexed { index, x -> arr[index] = x.toRaw(scope) }
}
However, this fails to compile with error No set method providing array access at arr[index] = x. I wrote the following code which compiles and runs as expected:
val floats = listOf(1f, 2f, 3f)
allocArray<FloatVar>(floats.size).also { arr ->
floats.forEachIndexed { index, x -> arr[index] = x }
}
The code is identical apart from the type used, leading me to believe that I was perhaps trying to assign to an rvalue. I went looking for VkDeviceQueueCreateInfoVar only to find this:
Also, any C type has the Kotlin type representing the lvalue of this type, i.e., the value located in memory rather than a simple immutable self-contained value. Think C++ references, as a similar concept. For structs (and typedefs to structs) this representation is the main one and has the same name as the struct itself, for Kotlin enums it is named ${type}Var, for CPointer it is CPointerVar, and for most other types it is ${type}Var.
This states that for structs, the lvalue representation has the same name as the struct (no Var suffix)... so VkDeviceQueueCreateInfo should represent an assignable lvalue, and I'm confused as to why I am unable to assign values to my array. It occurs to me that Kotlin's assignment does something very different to a C assignment, but I had assumed there would be an idiomatic way to perform a structure assignment.
I've looked through the other overloads and methods in NativePlacement to find one that allows me to initialize the values in the newly created array, and I found allocArray<T>(length: Long, initializer: T.(index: Long)->Unit), but this seems to suffer from the same problem.
How do I allocate and initialize an array of structures through cinterop?

Is that an in or in/out parameter? Doxygen, C++

If a pointer is passed to a function for read only, then this pointer is an IN parameter.
If a pointer is passed to a function for read only, but this function makes a copy of the pointer to have access to it in module related functions for read only operations, this pointer is still IN.
If the function still uses the pointer as read only, but the other module related functions use the pointer for write operations, what does that make the pointer?
An IN parameter, but without const? An in/out parameter?
Example of what I mean:
class SteeringWheel {
public: float rotation;
public: SteeringWheel(void) {
this->rotation = 0.f;
}
};
class Car {
private: SteeringWheel *steeringWheel;
public:
/**
* #param[?] steeringWheel Is the steering wheel in or in/out?
*/
Car (SteeringWheel *steeringWheel) {
this->steeringWheel = steeringWheel;
}
/**
* #param[in] degree Steering amount in degrees.
*/
void steer(float degree)
{
this->steeringWheel->rotation += degree;
}
};
int main(int argc, char **argv)
{
SteeringWheel steeringWheel();
/* car() uses steeringWheel as read only. */
Car car(&steeringWheel);
/* steer() uses steeringWheel from car() to write. */
car.steer(50.f);
return 0;
}
I believe that the in and out specifiers do not exactly mean what you think. From the doxygen documentation of the param tag:
The \param command has an optional attribute, (dir), specifying the
direction of the parameter. Possible values are "[in]", "[in,out]",
and "[out]", note the [square] brackets in this description. When a
parameter is both input and output, [in,out] is used as attribute.
The direction of the parameter usually mean the following:
in: The parameter is injected into the function as input, but not written to.
out: The parameter is injected into the function, but not as input. Rather, it is written to by the function.
in, out: The parameter is injected into the function as input and is eventually written to by the function.
In your example:
/**
* #param[?] steeringWheel Is the steering wheel in or in/out?
*/
Car (SteeringWheel *steeringWheel) {
this->steeringWheel = steeringWheel;
}
I think the steeringWheel parameter is in because you inject it and use it in your method. However, you never write to it (i.e. to the parameter itself), so it is not out. In other words, you only use your method to inject an address to your function, nothing else. The same apply for your second method, where you inject the degree parameter, but never write to it.
To clarify a bit more on the meaning of in and out, here is an example of an out parameter:
/**
* #param[out] p_param We write to the parameter!
*/
void makeFour(int * p_param)
{
*p_param = 4; // Out because of this line!
}
Notice that we write a new value directly into the parameter. This is the meaning of out: information comes out of the method through the parameter. You can now write:
int main()
{
int myInt = 0;
std::cout << myInt; // prints 0.
makeFour(&myInt); // p_param == &myInt here.
std::cout << myInt; // prints 4: the method wrote directly
// in the parameter (out)!
return 0;
}
Hope this helps!
It is not easy to decide, but I would still mark your parameter as in,out (or out), as it is a pointer to a non-const object, and you may change the state of that outside object directly or indirectly later - as in your example.
Marking it in hides the detail that the pointed SteeringWheel object may change later upon usage of Car.
Also, it can puzzle users why an input only pointer parameter is not marked const.
Making it in,out may not be accurate completely, but is surely more error prone.
An alternative could be something like the following (a note regarding the lifetime of the SteeringWheel should come handy here anyway):
/**
* #param[in] steeringWheel Pointer to the SteeringWheel object.
* #warning The memory address of the pointed object is saved.
* It must outlive this object, and can change upon usage of this object.
*/
Car (SteeringWheel *steeringWheel) {
this->steeringWheel = steeringWheel;
}
But I would just probably stick with marking it in,out.
Specifying the direction of parameters in C++ may be complicated, and frankly speaking, I am not too much in favor of them, as having tokens for pointers, references, and the keyword for constness provide enough information in the signature on how a parameter may be used. Thus, marking it in the DoxyPress documentation is a bit redundant, not expressive enough (as your example shows), and may get out of sync with the implementation. Documenting parameter directions may play a bigger role in case of other languages that lack these additional constructs in function signatures.

Literal field versus constant variable in C++/CLI

I'm going over some C++/CLI material and I've come across the concept of a literal field:
literal int inchesPerFoot = 12;
Is this preferable to a const because a const FIELD can't exist because a field cannot initialize itself...so:
class aClass
{
private:
const int aConstant = 1; // Syntax error.
...
};
Thanks,
Scott
A literal field is used for compile-time constants. It is associated with the class (similar to a "static const" field). In your example aConstant is a non-static const (an instance based) field--which is why you can't initialize it at the time of declaration (it would be initialized in the ctor's initialization list).
The difference between literal and static const fields is that referencing assemblies cannot use static const fields as compile-time constants, while literals can. However, within the same assembly, static const can be used as compile time constants.
FYI,
literal is equivalent to C#'s const.
initonly is equivalent to C#'s readonly.

What kind of pointer returned if I use "&" to get address of a value type in C++\CLI?

Suppose I write the following code:
public ref class Data
{
public:
Data()
{
}
Int32 Age;
Int32 year;
};
public void Test()
{
int age = 30;
Int32 year = 2010;
int* pAge = &age;
int* pYear = &year;
Data^ data = gcnew Data();
int* pDataYear = &data->Year; // pData is interior pointer and the compiler will throw error
}
If you compile the program, the compiler will throw error:
error C2440: 'initializing' : cannot convert from 'cli::interior_ptr' to 'int *'
So I learned the "&data->Year" is a type of interior pointer.
UPDATES: I tried to use "&(data->Year)", same error.
But how about pAge and pYear?
Are they native pointers, interior pointers or pinned pointers??
If I want to use them in the following native function:
void ChangeNumber(int* pNum);
Will it be safe to pass either pAge or pYear?
They (pAge and pYear) are native pointers, and passing them to a native function is safe. Stack variables (locals with automatic storage lifetime) are not subject to being rearranged by the garbage collector, so pinning is not necessary.
Copying managed data to the stack, then passing it to native functions, solves the gc-moving-managed-data-around problem in many cases (of course, don't use it in conjunction with callbacks that expect the original variable to be updated before your wrapper has a chance to copy the value back).
To get a native pointer to managed data, you have to use a pinning pointer. This can be slower than the method of copying the value to the stack, so use it for large values or when you really need the function to operate directly on the same variable (e.g. the variable is used in callbacks or multi-threading).
Something like:
pin_ptr<int> p = &mgd_obj.field;
See also the MSDN documentation

Creating a global "null" struct for re-use in C program?

Not sure what I'm doing wrong here. I have a struct that is used heavily through my program.
typedef struct _MyStruct {
// ... handful of non-trivial fields ...
} MyStruct;
I expect (read, intend) for lots of parts of the program to return one of these structs, but many of them should be able to return a "null" struct, which is a singleton/global. The exact use case is for the implementing function to say "I can't find what you asked me to return".
I assumed this would be a simple case of defining a variable in a header file, and initializing it in the .c file.
// MyStruct.h
// ... Snip ...
MyStruct NotFoundStruct;
-
// MyStruct.c
NotFoundStruct.x = 0;
NotFoundStruct.y = 0;
// etc etc
But the compiler complains that the initialization is not constant.
Since I don't care about what this global actually references in memory, I only care that everything uses the same global, I tried just removing the initialization and simply leaving the definition in the header.
But when I do this:
MyStruct thing = give_me_a_struct(some_input);
if (thing == NotFoundStruct) {
// ... do something special
}
Th compiler complains that the operands to the binary operator "==" (or "!=") are invalid.
How does one define such as globally re-usable (always the same memory address) struct?
This doesn't directly answer your question, but it won't fit in a comment...
If you have a function that may need to return something or return nothing, there are several options that are better than returning a "null struct" or "sentinel struct," especially since structs are not equality comparable in C.
One option is to return a pointer, so that you can actually return NULL to indicate that you are really returning nothing; this has the disadvantage of having significant memory management implications, namely who owns the pointer? and do you have to create an object on the heap that doesn't already exist on the heap to do this?
A better option is to take a pointer to a struct as an "out" parameter, use that pointer to store the actual result, then return an int status code indicating success or failure (or a bool if you have a C99 compiler). This would look something like:
int give_me_a_struct(MyStruct*);
MyStruct result;
if (give_me_a_struct(&result)) {
// yay! we got a result!
}
else {
// boo! we didn't get a result!
}
If give_me_a_struct returns zero, it indicates that it did not find the result and the result object was not populated. If it returns nonzero, it indicates that it did find the result and the result object was populated.
C doesn't allow global non-const assignments. So you must do this in a function:
void init() {
NotFoundStruct.x = 0;
NotFoundStruct.y = 0;
}
As for the comparison, C doesn't know how to apply a == operator to a struct. You can overload (redefine) the operator in C++, but not in C.
So to see if a return value is empty, your options are to
Have each function return a boolean value to indicate found or not, and return the struct's values via pointers through the argument list. (eg. bool found = give_me_a_struct(some_input, &thing);)
Return a pointer to a struct, which can be NULL if nothing exists. (eg. MyStruct* thing = give_me_a_struct(some_input);)
Add an additional field to the struct that indicates whether the object is valid.
The third option is the most generic for other cases, but requires more data to be stored. The best bet for your specific question is the first option.
// MyStruct.h
typedef struct _MyStruct {
// fields
} MyStruct;
extern MyStruct NotFoundStruct;
// MyStruct.c
#include "my_struct.h"
MyStruct NotFoundStruct = {0};
But since you can't use the == operator, you will have to find another way to distinguish it. One (not ideal) way is to have a bool flag reserved to indicate validity. That way, only that must be checked to determine if it's a valid instance.
But I think you should consider James's proposed solution instead
In the header:
// Structure definition then
extern MyStruct myStruct;
In the .c that contains global data
struct MyStruct myStruct
{
initialize field 1,
initialize field 2,
// etc...
};