How to use type inference so that possible immutable/const is removed? - d

How can I use type inference to remove immutable/const in a variable declaration? Is that possible at all?
immutable uint immutableX = 42;
// keep the type (uint) but remove the immutability
/* compiler magic */ mutableX = immutableX;
The non type inference solution is:
uint mutableX = immutableX;
A full example:
void main()
{
immutable uint immutableX = 42;
pragma(msg, "immutableX: ", typeof(immutableX));
assert(typeof(immutableX).stringof == "immutable(uint)");
// how to use type inference so that possible immutable/const is removed ?
// the expected type of mutableX is uint
auto mutableX = immutableX;
pragma(msg, "mutableX: ", typeof(immutableX));
// this should be true
assert(typeof(immutableX).stringof == "uint");
}

Depending on use case, there's std.traits.Unqual, which removes the outermost immutable, const, shared, etc:
import std.traits : Unqual;
immutable int a = 3;
Unqual!(typeof(a)) b = a;
static assert(is(typeof(b) == int));
An easier solution might be cast():
immutable int a = 3;
auto b = cast()a;
static assert(is(typeof(b) == int));
Which is correct depends on where and how you will use it.

Related

auto variable declaration without definition

I was wondering if there's an elegant solution for the following issue:
Let's say I'd like to have a variable holding a value with a pretty complex type and would the compiler to automatically infer it's type, but declare first and give value later in the code because of initialization in an if statement.
For example:
{
auto a;
if (some predicate)
a = init_a(1);
else
a = init_a(2);
}
Obviously this code doesn't compile, but the I think that the compiler has all the information it needs to infer the type.
If 'a' was just an int, this was not a problem, but if the type is a complex template, I don't want to have to write it (or in some cases even know it).
Also, i wouldn't want to call the default constructor of a and then write over it.
Possible solutions:
Template the type of 'a'.
initialize 'a' using a lambda and move the predicate into the lambda.
Just write the type of 'a' instead auto.
Use a void pointer/shared_ptr and then init 'a' on the heap.
Each of these has its own drawbacks.
Is there a more elegant solution for it?
The compiler doesn't have infinite lookahead what is happening further on in the code. It only knows what's happening at the current statement. Therefore it can't deduce any types without an initializer.
If you don't know the return-type of init_a then you could use decltype:
decltype(init_a(1)) a;
You can also use a lambda call to initialize the variable:
auto a = [ /* Captures needed for the condition... */ ]()
{
if (some_condition)
return init_a(1);
else
return init_a(2);
}(); // Call the lambda immediately
Or, as mentioned in many comments, use the ternary conditional expression:
auto a = some_condition ? init_a(1) : init_a(2);
There's a technique called "Immediately Invoked Lambda Expression" that is using lambda to initialize a variable in a complex way. Using this approach your a can be const which improves const-correctness. More details here.
For a simple binary predicate, consider just using the ternary operator:
struct A { int a; };
A initA(int a) { return A{a}; }
bool somePredicate(int input) { return input == 42; }
int main() {
const auto input = 42;
const auto a = somePredicate(input) ? initA(1) : initA(2);
}
for more complex initialization logic (beyond a binary case), wrap the initialization logic in a lambda:
struct A { int a; };
A initA(int a) { return A{a}; }
bool somePredicate(int input) { return input == 42; }
int main() {
const auto input = 42;
const auto a = []() {
if (somePredicate(input)) { return initA(1); }
else if (input == 100) { return initA(100); }
else { return initA(2); }}();
}
Both these approaches come with additional possibility of making the variable to be initialized const.
If the return types of your lambda are different but convertible to some type then you can force the return type (note the -> is mandatory when specifying a return type):
auto a = [=]() -> ConvertedType {
if (some_predicate) {
return CovertibleType1(1);
} else if (other_predicate) {
return ConvertibleType2(2);
}
return ConvertibleType3(3);
}();
Though I realize this basically defeats the auto declaration...

Clang AST matcher for variables compared to different variable types

I am new to clang-tidy and the following is practice so I can move to more complex matchers and tools.
Lets say we have
typedef int my_type;
void foo()
{
int x = 0;//this should be identified as need to be fixed
my_type z = 0;
if( x == z){
//match this case
}
}
My goal is to identify variables that are compared against "my_type" in order to fix their declarations by changing their types to my_type.
Right now I am tryng to do the following
auto my_type_decl = varDecl(hasType(asString("my_type")));
auto my_type_decl_exp= declRefExpr(to(my_type_decl));
auto binop = binaryOperator(has(implicitCastExpr(has(my_type_decl_exp))));
auto other_decl_exp = declRefExpr(hasAncestor(binop), unless(to(my_type_decl)));
//get ancestor functionDecl
//get descendant varDecls that match the other_decl_exp
The problem here is that I disregard context.
What would be the correct way to go about something like this?
You can bind node matchers to a name, and then retrieve those nodes from the match result.
For example:
// Match binary operators
binaryOperator(
// that are equality comparisons,
hasOperatorName("=="),
// where one side refers to a variable
hasEitherOperand(ignoringImpCasts(declRefExpr(to(varDecl(
// whose type is a typedef or type alias
hasType(typedefNameDecl(
// named "::my_type"
hasName("::my_type"),
// that aliases any type, which is bound to the name "aliased",
hasType(type().bind("aliased"))))))))),
// and where one side refers to a variable
hasEitherOperand(ignoringImpCasts(declRefExpr(to(varDecl(
// whose type is the same as the type bound to "aliased",
// which is bound to the name "declToChange".
hasType(type(equalsBoundNode("aliased")))).bind("declToChange"))))));
And then:
const auto *declToChange = result.Nodes.getNodeAs<VarDecl>("declToChange");
Note that this matches the equality comparisons, so declToChange might point to the same VarDecl in multiple matches.
In the following example, this matcher would produce two matches with declToChange bound to x, and none with declToChange bound to y:
typedef int my_type;
void foo() {
int x = 0;
int y = 0;
my_type z = 0;
if (x == z) {
}
if (z == x) {
}
}

How do I cast int** to void**?

With the following snippet:
int n = 11;
int* c = &n;
void** v = &c;
I receive the following error in visual studio:
the value of type int** cannot be used to initialize an entity of type void **.
This works fine:
int n = 11;
int* c = &n;
void* v = c;
But this code snippet is for a larger problem in someone's library.
What am I doing wrong with casting a variable to void**?
Complete Example
Using the caen digitizer library the way they try to collect data from the peripheral device has this prototype:
/******************************************************************************
* X742_DecodeEvent(char *evtPtr, void **Evt)
* Decodes a specified event stored in the acquisition buffer writing data in Evt memory
* Once used the Evt memory MUST be deallocated by the caller!
*
* [IN] EventPtr : pointer to the requested event in the acquisition buffer (MUST BE NULL)
* [OUT] Evt : event structure with the requested event data
* : return 0 = Success;
******************************************************************************/
int32_t X742_DecodeEvent(char *evtPtr, void **Evt);
And this is the implementation:
int32_t X742_DecodeEvent(char *evtPtr, void **Evt) {
CAEN_DGTZ_X742_EVENT_t *Event;
uint32_t *buffer;
char chanMask;
uint32_t j,g,size;
uint32_t *pbuffer;
uint32_t eventSize;
int evtSize,h;
evtSize = *(long *)evtPtr & 0x0FFFFFFF;
chanMask = *(long *)(evtPtr+4) & 0x0000000F;
evtPtr += EVENT_HEADER_SIZE;
buffer = (uint32_t *) evtPtr;
pbuffer = (uint32_t *) evtPtr;
eventSize = (evtSize * 4) - EVENT_HEADER_SIZE;
if (eventSize == 0) return -1;
Event = (CAEN_DGTZ_X742_EVENT_t *) malloc(sizeof(CAEN_DGTZ_X742_EVENT_t));
if (Event == NULL) return -1;
memset( Event, 0, sizeof(CAEN_DGTZ_X742_EVENT_t));
for (g=0; g<X742_MAX_GROUPS; g++) {
if ((chanMask >> g) & 0x1) {
for (j=0; j<MAX_X742_CHANNEL_SIZE; j++) {
Event->DataGroup[g].DataChannel[j]= malloc(X742_FIXED_SIZE * sizeof (float));
if (Event->DataGroup[g].DataChannel[j] == NULL) {
for (h=j-1;h>-1;h++) free(Event->DataGroup[g].DataChannel[h]);
return -1;
}
}
size=V1742UnpackEventGroup(g,pbuffer,&(Event->DataGroup[g]));
pbuffer+=size;
Event->GrPresent[g] = 1;
}
else {
Event->GrPresent[g] = 0;
for (j=0; j<MAX_X742_CHANNEL_SIZE; j++) {
Event->DataGroup[g].DataChannel[j] = NULL;
}
}
}
*Evt = Event;
return 0;
}
I use this by:
CAEN_DGTZ_X742_EVENT_t* Evt = NULL; // Creating my event pointer
//Doing some config of the device
X742_DecodeEvent(evtptr, &Evt); //Decode the event data for me to read (Throws error)
Hope this gives some context.
void** means a pointer to a void* object. But there is no void* object in that code to point at! void** does NOT mean "a pointer to any kind of pointer", so please avoid using it as such. If you have a pointer to something which might be an int*, might be a double*, or etc., void* is a better type than void**. Even better would be a template or std::variant or std::any.
But if you have to use a library that is using void** to mean "a pointer to a pointer to a type unknown at compile time" or something like that, you might need to create a void* pointer to work with, or might need to add in casts to get around the fact that the compiler doesn't like this conversion (for good reason). The problem is, there are at least two reasonable ways to do this! (They will end up doing exactly the same thing on many common computer architectures, but this is not guaranteed.)
// LibraryFunc1 takes a void** argument that somehow means an int* pointer.
// But which call is correct?
int* data_in = generate_data();
LibraryFunc1(reinterpret_cast<void**>(&data_in)); // ?
void* p1 = data_in;
LibraryFunc1(&p1); // ?
// LibraryFunc2 returns a void** argument that somehow means an int* pointer.
void** p2 = LibraryFunc2();
int* data_out_1 = static_cast<int*>(*p2); // ?
int* data_out_2 = *reinterpret_cast<int**>(p2); // ?
Based on the function definition shown, the safe usage is unfortunately:
void* tmpEvt;
X742_DecodeEvent(evtptr, &tmpEvt);
auto* Evt = static_cast<CAEN_DGTZ_X742_EVENT_t*>(tmpEvt);
since the library function assumes at *Evt = Event; that *Evt is actually a void* object it can modify. It may usually work to do the simpler thing instead:
CAEN_DGTZ_X742_EVENT_t* Evt = NULL;
X742_DecodeEvent(evtptr, reinterpret_cast<void**>(&Evt));
but this is undefined behavior by the C++ Standard, and might do the wrong thing on some architectures.
You could make the correct way easier by wrapping it in a function:
inline CAEN_DGTZ_X742_EVENT_t* Get_X742_DecodeEvent(char* evtPtr)
{
void* tmpEvt;
X742_DecodeEvent(evtPtr, &tmpEvt);
return static_cast<CAEN_DGTZ_X742_EVENT_t*>(tmpEvt);
}
What am I doing wrong with casting a variable to void**?
There is no meaningful way to convert int** to void**, so what you're trying to do is wrong.
What you may do is
int n = 11;
void* c = &n;
void** v = &c;
But without a complete example, it is not possible to say whether applies to your problem.
That's simply how the language works.
void * pointers get special treatment: a pointer to an arbitrary type can be converted to a pointer to void (as long as doing so doesn't remove cv-qualifiers from the pointer).
void ** gets none of that special treatment. It's just a regular pointer type, like int **.
int32_t X742_DecodeEvent(char *evtPtr, void **Evt)
Since you want to pass CAEN_DGTZ_X742_EVENT_t ** to your function, you should change the parameter type accordingly: CAEN_DGTZ_X742_EVENT_t **Evt.
In comments you were suggested to use void ** v = (void**)&c;.
While you could probably make it work in practice, strictly speaking any access to *v would violate strict aliasing and cause undefined behavior. I wouldn't use that solution.

How to Pass Struct Data Member into Function

I want to be able to pass a struct member into a function:
struct threeBuckets {
int bucketA;
int bucketB;
int bucketC;
};
threeBuckets allCombinations[512000] = {{0,0,0}};
int totalCombinations = 1;
int counter = 0;
//note that pourer, receiver, and other are one of the struct members (bucketA, bucketB, and bucketC)
void pour(pourer, receiver, int receiverCap, other) {
int finalTriple[3];
allCombinations[totalCombinations].bucketA = allCombinations[counter].bucketA;
allCombinations[totalCombinations].bucketB = allCombinations[counter].bucketB;
allCombinations[totalCombinations].bucketC = allCombinations[counter].bucketC;
allCombinations[totalCombinations].receiver = allCombinations[totalCombinations].receiver + allCombinations[counter].pourer;
allCombinations[totalCombinations].pourer = 0;
if (allCombinations[totalCombinations].receiver > receiverCap) {
allCombinations[totalCombinations].pourer = allCombinations[totalCombinations].pourer + allCombinations[totalCombinations].receiver - receiverCap;
allCombinations[totalCombinations].receiver = receiverCap;
}
finalTriple[0] = allCombinations[totalCombinations].bucketA;
finalTriple[1] = allCombinations[totalCombinations].bucketB;
finalTriple[2] = allCombinations[totalCombinations].bucketC;
//some more irrelevant code
}
As I've hopefully made clear, the parameters pourer, receiver, and other are bucketA, bucketB, and bucketC (in no particular order, the order does change depending on when I call the function.) There are several places where I want to modify the instance
allCombinations[totalCombinations].pourer
for example. How do I use the struct member as a parameter, and what type do I use to specify it?
Note: I'm mostly a beginner and am new to StackOverflow, so if anything else I'm doing is wrong, please feel free to tell me.
Note 2: If any of you do or have done USACO, you might recognize this problem as the milk3 training gateway problem. This might aid you if you don't know what I'm doing here.
It sounds like you need to use pointer to member variable for the argument types in pour.
void pour(double threeBuckets::(*pourer) ,
double threeBuckets::(*receiver),
int receiverCap,
double threeBuckets::(*other)) {
...
}
In the function, change the use of
allCombinations[totalCombinations].pourer
allCombinations[totalCombinations].receiver
allCombinations[totalCombinations].other
by
allCombinations[totalCombinations].*pourer
allCombinations[totalCombinations].*receiver
allCombinations[totalCombinations].*other
respectively.
At the point of calling the function, use:
pour(&threeBuckets::bucketA,
&threeBuckets::bucketB,
0, // Any appropriate value
&threeBuckets::bucketC);
Another option that is worth considering is:
Change threeBuckets to use an array.
Change the arguments to pour to be indices to the array.
struct threeBuckets {
int buckets[3];
};
void pour(int pourerIndex ,
int receiverIndex,
int receiverCap,
int otherIndex)) {
...
}
Then, instead of using
allCombinations[totalCombinations].pourer
allCombinations[totalCombinations].receiver
allCombinations[totalCombinations].other
use
allCombinations[totalCombinations].buckets[pourerIndex]
allCombinations[totalCombinations].buckets[receiverIndex]
allCombinations[totalCombinations].buckets[otherIndex]
Of course, change the call to use indices.
pour(0,
1
0, // Any appropriate value
2);

A variable that is read-only after assignment at run-time?

Fairly new programmer here, and an advance apology for silly questions.
I have an int variable in a program that I use to determine what the lengths of my arrays should be in some of my structures. I used to put it in my header as a const int. Now, I want to fork my program to give the variable different values depending on the arguments given in, but keep it read-only after I assign it at run-time.
A few ideas I've had to do this. Is there a preferred way?
Declare a const int * in my header and assigning it to a const int in my main function, but that seems clunky.
Make it a plain int in my main function.
Pass the variable as an argument when the function is called.
Something else I haven't thought of yet.
I'd use a function-static variable and a simple function. Observe:
int GetConstValue(int initialValue = 0)
{
static int theValue = initialValue;
return theValue;
}
Since this is a function-level static variable, it is initialized only the first time through. So the initialValue parameter is useless after the first run of the function. Therefore, all you need to do is ensure that the first call of the function is the one that initializes it.
C++ doesn't have a built-in solution for this, but if you really want to make sure that your int is only assigned once, you can build your own special int class:
class MyConstInt
{
public:
MyConstInt(): assigned(false) {}
MyConstInt& operator=(int v)
{
assert(!assigned);
value = v;
assigned = true;
return *this;
}
operator int() const
{
assert(assigned);
return value;
}
private:
int value;
bool assigned;
};
MyConstInt mi;
// int i = mi; // assertion failure; mi has no value yet
mi = 42;
// mi = 43; // assertion failure; mi already has a value
int* array = new int[mi];
When exactly do you know the correct value? If you read it from a file or whatever, you can just say:
const int n = determine_correct_value();
I'm tempted to say that what you want doesn't make sense. A constant is something that doesn't change its value, not something that maybe changes its value once or twice. If you want a global variable, just make it non-constant.
On the other hand, if you have scope-constant values, you would just declare and initialize them at the same time, following the general C++ guideline to declare as close to the usage site as possible. For example, mark the use of constants in the following local scope:
for (auto it = v.begin(), end = v.end(); it != end; ++it)
{
const Foo & x = *it;
const std::size_t n = x.get_number_of_bars();
// use x and n ...
const bool res = gobble(x, zip(n));
if (res && shmargle(x)) { return 8; }
}
Here the compiler may even choose not to generate any special code for the variables at all if their value is already known through other means.