This question already has answers here:
Bit-fields "In-class initialization" results in "error: lvalue required as left operand of assignment"
(5 answers)
Closed 7 years ago.
This works:
struct A {
unsigned int x = 0;
};
This also works:
struct A {
unsigned int x : 1;
};
Is it possible to combine the two? I.e., initialize and specify size simultaneously? Or do I need to explicitly write a constructor to do this?
Let's take a quick look at the grammar of [class.mem]:
member-declarator:
declarator virt-specifier-seqopt pure-specifieropt
declarator brace-or-equal-initializeropt
identifieropt attribute-specifier-seqopt : constant-expression
Bit fields are the third option, members with initializer are the second. So you cannot have both.
However, you can initialize named bit fields in constructor initializer lists, just like any other non-static data member. (But you cannot initialize unnamed bit fields, since they are not members.)
Related
This question already has an answer here:
Generic Structs with Go
(1 answer)
Closed 8 months ago.
I try to run examples from the design draft (The Next Step for Generics) on
go2go.playground
type Pair(type T) struct { f1, f2 T }
, but get an error
prog.go2:14:11: expected type, found 'type' (and 1 more errors)
Where can I find actual go generics design draft?
You're looking at outdated design draft.
This one is current: https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md
So, it's not:
type Pair(type T) struct { f1, f2 T }
But:
type Pair[T any] struct { f1, f2 T }
That's old syntax since a few weeks ago. Try
type Pair[T any] struct { f1, f2 T }
Note that square brackets are now used instead of round brackets and the type keyword is no longer used. You also must use the any constraint, whereas previously you could leave the constraint out if there was no restriction on the type parameter.
BTW Conventionally Pair refers to a struct with 2 different types for the 2 fields like type Pair[T1, T2 any] struct { first T1; second T2 }
See go2go Playground for example code that builds.
As mentioned in the first paragraph of the 2019 design draft the new draft is https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md
This question already has answers here:
Defining a method for a struct only when a field is a certain enum variant?
(1 answer)
Is there a way to use existing structs as enum variants?
(2 answers)
Can struct-like enums be used as types?
(2 answers)
Closed 2 years ago.
With this definition of Strct, it is possible for values to hold any variant of the Test enum:
enum Test {
A,
B,
C,
}
struct Strct {
values: Vec<Test>,
}
Is there a way to enforce it to hold only a specific variant of the enum? E.g. Vec<A> or Vec<B> or Vec<C> for that specific case.
std::move() is stealing the string value whereas not an int, please help me.
int main()
{
int i = 50;
string str = "Mahesh";
int j = std::move(i);
string name = std::move(str);
std::cout <<"i: "<<i<<" J: "<<j <<std::endl;
std::cout <<"str: "<<str<<" name: "<<name <<std::endl;
return 0;
}
Output
i: 50 J: 50
str: name: Mahesh
std::move is a cast to an rvalue reference. This can change overload resolution, particularly with regard to constructors.
int is a fundamental type, it doesn't have any constructors. The definition for int initialisation does not care about whether the expression is const, volatile, lvalue or rvalue. Thus the behaviour is a copy.
One reason this is the case is that there is no benefit to a (destructive) move. Another reason is that there is no such thing as an "empty" int, in the sense that there are "empty" std::strings, and "empty" std::unique_ptrs
std::move() itself doesn't actually do any moving. It is simply used to indicate that an object may be moved from. The actual moving must be implemented for the respective types by a move constructor/move assignment operator.
std::move(x) returns an unnamed rvalue reference to x. rvalue references are really just like normal references. Their only purpose is simply to carry along the information about the "rvalue-ness" of the thing they refer to. When you then use the result of std::move() to initialize/assign to another object, overload resolution will pick a move constructor/move assignment operator if one exists. And that's it. That is literally all that std::move() does. However, the implementation of a move constructor/move assignment operator knows that the only way it could have been called is when the value passed to it is about to expire (otherwise, the copy constructor/copy assignment operator would have been called instead). It, thus, can safely "steal" the value rather than make a copy, whatever that may mean in the context of the particular type.
There is no general answer to the question what exactly it means to "steal" a value from an object. Whoever defines a type has to define whether it makes sense to move objects of this type and what exactly it means to do so (by declaring/defining the respective member functions). Built-in types don't have any special behavior defined for moving their values. So in the case of an int you just get what you get when you initialize an int with a reference to another int, which is a copy…
I found they're different, and the language standard says what kind of type each statement should retrieve(difference between variable and expression). But I really wish to know why these 2 kinds of types should be different?
#include<stdio.h>
int x=0;
decltype((x)) y=x;
int main()
{
y=2;
printf("%d,",x);
decltype((1+2))&z=x;//OK (1+2) is an express, but why decltype should differ?
z=3;
printf("%d\n",x);
return 0;
}
The running result is '2,3'
So why decltype((int)) is int& by design, what's the consideration of C++ language design here? Any syntax consistency that requires such a design? (I don't wish to get "This is by design")
Thanks for your explanations.
If you read e.g. this decltype reference you will see
2) If the argument is an unparenthesized id-expression or an unparenthesized class member access expression, ...
3) If the argument is any other expression...
...
b) if the value category of expression is lvalue, then decltype yields T&;
[Emphasis mine]
And then a little further down the note
Note that if the name of an object is parenthesized, it is treated as an ordinary lvalue expression, thus decltype(x) and decltype((x)) are often different types.
Because you use a parenthesized expression it is treated as an lvalue, meaning that 3.b above is active and decltype((x)) gives you int& if x is int.
It should be noted that while the reference isn't authoritative it is derived from the specification and generally reliable and correct.
From the C++11 specification ISO/IEC 14882:2011, section 7.1.6.2 [dcl.type.simple], sub-section 4:
The type denoted by decltype(e) is defined as follows:
— if e is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;
— otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;
— otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
— otherwise, decltype(e) is the type of e
And with an example:
struct A { double x; };
const A* a = new A();
...
decltype((a->x)) x4 = x3; // type is const double&
Basically exactly what the previously linked reference said.
With your example, e in the specification is (x) (since you have declspec((x))). Now the first case doesn't fit because (x) is not an unparenthesized expression. The second case doesn't fit because (x) isn't an xvalue. The third case matches though, (x) is an lvalue of type int, leading decltype((x)) to be int&.
So the answer to your query is simply: Because the specification says so.
Well, The answer I see here is that "the specification says so". I looked into stroustrup's original drafts of decltype and this is what it says.
if expr in decltype(expr) is a variable or formal parameter the
programmer can trace down the variable’s or parameter’s declaration,
and the result of decltype is exactly the declared type. If expr is a
function invocation, the programmer can perform manual overload
resolution; the result of the decltype is the return type in the
prototype of the best matching function. The prototypes of the
built-in operators are defined by the standard, and if some are
missing, the rule that an lvalue has a reference type applies.
Look at the last statement here, I think that explains. Since parenthesis are built-in operators to indicate and expression.
This question already has an answer here:
How to specify the representation type for an enum in Rust to interface with C++?
(1 answer)
Closed 6 years ago.
Given a simple enum with a few un-typed values, it might be desirable that the size of this enum use a smaller integral type then the default. For example, this provides the ability to store the enum in an array of u8.
enum MyEnum {
A = 0,
B,
C,
}
It's possible to use a u8 array and compare them against some constants, but I would like to have the benefit of using enums to ensure all possibilities are handled in a match statement.
How can this be specified so its size_of matches the desired integer type?
This can be done using the representation (repr) specifier.
#[repr(u8)]
enum MyEnum { A = 0, B, C, }
Assigned values outside the range of the type will raise a compiler warning.