Are there any drawbacks to relying on a synthesized memberwise initializer in a container view? - swiftui

Obviously synthesized memberwise initializers make code less cluttered and therefore easier to read, but is there a risk of a performance hit when relying on them in a container view?
A container view could be written thus:
struct ContainerCustomInitView<Content>: View where Content: View {
let content: Content
init(#ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
ZStack {
Color(.orange)
content
}
}
}
In this example, a custom initializer calls the passed-in closure and stores its result in a property. This should ensure that the closure is only called once per instance of the container.
The equivalent implementation relying on a synthesized memberwise initializer would look like this:
struct ContainerSynthesizedMemberwiseInitView<Content>: View where Content: View {
#ViewBuilder
let content: () -> Content
var body: some View {
ZStack {
Color(.orange)
content()
}
}
}
Here, there is no choice but to call the closure within the body property. Is there any danger that the code defining the body property’s value could be called multiple times and therefore content() would be called a likewise number times? I assume that it can’t and the testing I’ve done seems confirm this assumption.
But before I do this sort of thing all over the place, (and potentially later on start scratching my head because my app is running at a snail’s pace), can somebody with a more authoritative knowledge advise me on this concern please?

Related

What does explicit *this object parameter offer in C++23?

In C++23, deducing this is finally added to the standard.
Based on what I've read from the proposal, it opens up a new way of creating mixins, and possible to create recursive lambdas.
But I'm confused if this parameter creates a "copy" without using templates since there is no reference or does the explicit this parameter have its own rules of value category?
Since:
struct hello {
void func() {}
};
may be the equivalent of:
struct hello {
void func(this hello) {}
};
But their type is different because for &hello::func, the first one gives void(hello::*)(), while the second one gives void(*)(hello)
For instance, I have this simple function:
struct hello {
int data;
void func(this hello self) {
self.data = 22;
}
};
Doesn't this parameter need to be a reference to change the value of hello type? Or it basically follows the cv-ref qualifier rules of member function as same as before?
Section 4.2.3 of the paper mentions that "by-value this" is explicitly allowed and does what you expect. Section 5.4 gives some examples of when you would want to do this.
So in your example, the self parameter is modified and then destroyed. The caller's hello object is never modified. If you want to modify the caller's object, you need to take self by reference:
void func(this hello& self) {
self.data = 22;
}

Lambda <-> closure equivalence in C++

I was watching a video called Lambda? You Keep Using that Letter by Kevlin Henney, where he states that closures and objects are fundamentaly equivalent:
He then proves his point by this javascript code which implement a stack as a closure:
const newStack = () => {
const items = []
return {
depth: () => items.lengh,
top: () => items[0],
push: newTop => { items.unshift(newTop) },
pop: () => { items.shift() },
}
}
The advantage of a closure versus a class is that its state is really hidden, whereas a private member is more "inaccessible" than "hidden".
I tried to do something equivalent in C++. However, it seems that it is difficult to express this in C++.
My current version is there, and it has two major drawbacks:
it does compile, but it will not work (the inner shared_ptris released immediately after the closure creation)
is a bit verbose : depth, top, push and pop are repeated 3 times.
auto newStack = []() {
auto items = std::make_shared<std::stack<int>>();
auto depth = [&items]() { return items->size();};
auto top = [&items]() { return items->top(); };
auto push = [&items](int newTop) { items->push(newTop); };
auto pop = [&items]() { items->pop(); };
struct R {
decltype(depth) depth;
decltype(top) top;
decltype(push) push;
decltype(pop) pop;
};
return R{ depth, top, push, pop};
};
godbolt version here
Is there a working way to do it in C++?
Yes, of course there's a better way to do it in C++: don't use a lambda.
A lambda expression defines a class. A closure is an instance of that class--an object. We don't need comparisons to other languages to tell us that--it's exactly how lambdas and closures are defined in C++. §[expr.prim.lambda.closure]:
The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type, whose properties are described below.
But (and this is an important point) at least in C++, a lambda expression defines a class with a very limited public interface. Specifically, it provides an overload of operator(), and if it doesn't capture anything, a conversion to pointer to function. If it does capture something, it also defines a constructor to do the capturing. And of course if it captures things, it defines member variables to hold whatever it captures.
But that's all it really defines. It's not that it's doing a better job of hiding whatever else it may contain. It's that it really doesn't contain anything else.
In your case, you're trying to define a type that has four separate member functions that all operate on some state they share. As you've shown, it's sort of possible to do that externalizing the state so you have something nearly equivalent to some C code (or something on that order) that simply has data and some functions that operate on that data. And yes, you can push them together into a structure to do at least some imitation of a class with member functions.
But you're pretty much fighting against the system (so to speak) to do that in C++. Lambdas/closures (as they're defined in C++) are not intended to let you define things that have multiple separate entry points, each carrying out separate actions on shared data. As Samuel Johnson's old line says, "[It] is like a dog walking on its hind legs. It is not done well; but you are surprised to find it done at all."

cannot use MockDaoInterface literal (type MockDaoInterface) as type s3.DaoInterface in assignment: MockDaoInterface does not implement s3.DaoInterface [duplicate]

There are already several Q&As on this "X does not implement Y (... method has a pointer receiver)" thing, but to me, they seems to be talking about different things, and not applying to my specific case.
So, instead of making the question very specific, I'm making it broad and abstract -- Seems like there are several different cases that can make this error happen, can someone summary it up please?
I.e., how to avoid the problem, and if it occurs, what are the possibilities? Thx.
This compile-time error arises when you try to assign or pass (or convert) a concrete type to an interface type; and the type itself does not implement the interface, only a pointer to the type.
Short summary: An assignment to a variable of interface type is valid if the value being assigned implements the interface it is assigned to. It implements it if its method set is a superset of the interface. The method set of pointer types includes methods with both pointer and non-pointer receiver. The method set of non-pointer types only includes methods with non-pointer receiver.
Let's see an example:
type Stringer interface {
String() string
}
type MyType struct {
value string
}
func (m *MyType) String() string { return m.value }
The Stringer interface type has one method only: String(). Any value that is stored in an interface value Stringer must have this method. We also created a MyType, and we created a method MyType.String() with pointer receiver. This means the String() method is in the method set of the *MyType type, but not in that of MyType.
When we attempt to assign a value of MyType to a variable of type Stringer, we get the error in question:
m := MyType{value: "something"}
var s Stringer
s = m // cannot use m (type MyType) as type Stringer in assignment:
// MyType does not implement Stringer (String method has pointer receiver)
But everything is ok if we try to assign a value of type *MyType to Stringer:
s = &m
fmt.Println(s)
And we get the expected outcome (try it on the Go Playground):
something
So the requirements to get this compile-time error:
A value of non-pointer concrete type being assigned (or passed or converted)
An interface type being assigned to (or passed to, or converted to)
The concrete type has the required method of the interface, but with a pointer receiver
Possibilities to resolve the issue:
A pointer to the value must be used, whose method set will include the method with the pointer receiver
Or the receiver type must be changed to non-pointer, so the method set of the non-pointer concrete type will also contain the method (and thus satisfy the interface). This may or may not be viable, as if the method has to modify the value, a non-pointer receiver is not an option.
Structs and embedding
When using structs and embedding, often it's not "you" that implement an interface (provide a method implementation), but a type you embed in your struct. Like in this example:
type MyType2 struct {
MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: m}
var s Stringer
s = m2 // Compile-time error again
Again, compile-time error, because the method set of MyType2 does not contain the String() method of the embedded MyType, only the method set of *MyType2, so the following works (try it on the Go Playground):
var s Stringer
s = &m2
We can also make it work, if we embed *MyType and using only a non-pointer MyType2 (try it on the Go Playground):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = m2
Also, whatever we embed (either MyType or *MyType), if we use a pointer *MyType2, it will always work (try it on the Go Playground):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = &m2
Relevant section from the spec (from section Struct types):
Given a struct type S and a type named T, promoted methods are included in the method set of the struct as follows:
If S contains an anonymous field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
If S contains an anonymous field *T, the method sets of S and *S both include promoted methods with receiver T or *T.
So in other words: if we embed a non-pointer type, the method set of the non-pointer embedder only gets the methods with non-pointer receivers (from the embedded type).
If we embed a pointer type, the method set of the non-pointer embedder gets methods with both pointer and non-pointer receivers (from the embedded type).
If we use a pointer value to the embedder, regardless of whether the embedded type is pointer or not, the method set of the pointer to the embedder always gets methods with both the pointer and non-pointer receivers (from the embedded type).
Note:
There is a very similar case, namely when you have an interface value which wraps a value of MyType, and you try to type assert another interface value from it, Stringer. In this case the assertion will not hold for the reasons described above, but we get a slightly different runtime-error:
m := MyType{value: "something"}
var i interface{} = m
fmt.Println(i.(Stringer))
Runtime panic (try it on the Go Playground):
panic: interface conversion: main.MyType is not main.Stringer:
missing method String
Attempting to convert instead of type assert, we get the compile-time error we're talking about:
m := MyType{value: "something"}
fmt.Println(Stringer(m))
To keep it short and simple, let say you have a Loader interface and a WebLoader that implements this interface.
package main
import "fmt"
// Loader defines a content loader
type Loader interface {
load(src string) string
}
// WebLoader is a web content loader
type WebLoader struct{}
// load loads the content of a page
func (w *WebLoader) load(src string) string {
return fmt.Sprintf("I loaded this page %s", src)
}
func main() {
webLoader := WebLoader{}
loadContent(webLoader)
}
func loadContent(loader Loader) {
loader.load("google.com")
}
The above code will give you this compile time error
./main.go:20:13: cannot use webLoader (type WebLoader) as type Loader
in argument to loadContent:
WebLoader does not implement Loader (Load method has pointer receiver)
To fix it you only need to change webLoader := WebLoader{} to following:
webLoader := &WebLoader{}
Why this will fix the issue? Because you defined this function func (w *WebLoader) Load to accept a pointer receiver. For more explanation please read #icza and #karora answers
Another case when I have seen this kind of thing happening is if I want to create an interface where some methods will modify an internal value and others will not.
type GetterSetter interface {
GetVal() int
SetVal(x int) int
}
Something that then implements this interface could be like:
type MyTypeA struct {
a int
}
func (m MyTypeA) GetVal() int {
return a
}
func (m *MyTypeA) SetVal(newVal int) int {
int oldVal = m.a
m.a = newVal
return oldVal
}
So the implementing type will likely have some methods which are pointer receivers and some which are not and since I have quite a variety of these various things that are GetterSetters I'd like to check in my tests that they are all doing the expected.
If I were to do something like this:
myTypeInstance := MyType{ 7 }
... maybe some code doing other stuff ...
var f interface{} = myTypeInstance
_, ok := f.(GetterSetter)
if !ok {
t.Fail()
}
Then I won't get the aforementioned "X does not implement Y (Z method has pointer receiver)" error (since it is a compile-time error) but I will have a bad day chasing down exactly why my test is failing...
Instead I have to make sure I do the type check using a pointer, such as:
var f interface{} = new(&MyTypeA)
...
Or:
myTypeInstance := MyType{ 7 }
var f interface{} = &myTypeInstance
...
Then all is happy with the tests!
But wait! In my code, perhaps I have methods which accept a GetterSetter somewhere:
func SomeStuff(g GetterSetter, x int) int {
if x > 10 {
return g.GetVal() + 1
}
return g.GetVal()
}
If I call these methods from inside another type method, this will generate the error:
func (m MyTypeA) OtherThing(x int) {
SomeStuff(m, x)
}
Either of the following calls will work:
func (m *MyTypeA) OtherThing(x int) {
SomeStuff(m, x)
}
func (m MyTypeA) OtherThing(x int) {
SomeStuff(&m, x)
}
Extend from above answers (Thanks for all of your answers)
I think it would be more instinctive to show all the methods of pointer / non pointer struct.
Here is the playground code.
https://play.golang.org/p/jkYrqF4KyIf
To summarize all the example.
Pointer struct type would include all non pointer / pointer receiver methods
Non pointer struct type would only include non pointer receiver methods.
For embedded struct
non pointer outer struct + non pointer embedded struct => only non pointer receiver methods.
non pointer outer struct + pointer embedded struct / pointer outer struct + non pointer embedded struct / pointer outer struct + pointer embedded struct => all embedded methods

Replace void rvalue reference

I am writing a kind of message passing interface, where a frontend request a variable of type Var to a backend. In the most simple form, it reads:
Var backend();
Var interface() {return backend();}
Var frontend() {return interface();}
Unfortunately, although interface implementation is aware of type Var, its signature is not. Had a void rvalue reference existed in c++, I would use something like
void&& interface();
with proper casting, because I want this process to stay copy free as most as possible, and I do not want Var constructor to be called. I came up with this hack:
void interface(void* p) {new (p) Var(backend());}
Var get()
{
char hack[sizeof(Var)];
impl_get(static_cast<void*>(&hack));
return std::move(*reinterpret_cast<A*>(hack));
}
Which, as far as I know, only calls the move constructor of Var (if defined). Is this solution standard and safe and is there any cleaner way of doing that?

Is there a decltype equivalent in Swift?

In C++11 and latter, it is possible to use a compile time function like syntax named decltype() to reuse declaration type of a variable to declare another one without rewriting the type signature. Is there any equivalent syntactic tool in Swift?
C++ Example:
class SomeClass {
public:
SomeVeryLongTypeName* my_prop;
}
void foo() {
SomeClass my_var = SomeClass();
// Below code is a variable declaration, not a function call
declytype(my_var.my_prop) some_prop = nullptr;
// Below is same as above
SomeVeryLongTypeName* some_prop = nullptr;
}
There is, as far as I know, no direct equivalent syntactic tool readily available in Swift.
For something slightly similar you could, however, make use of generics to gain access to (at compile time) a metatype (grammar: metatype-type → type­.­Type), whereafter you can use an initializer expression to construct an instance of the concrete type (of the metatype).
protocol Initializable {
init()
}
typealias SomeVeryLongTypeName = Int
extension SomeVeryLongTypeName : Initializable {}
class SomeClass {
let my_prop : SomeVeryLongTypeName
required init() { my_prop = 1 }
}
func declmetatype<T: Initializable>(_: T) -> T.Type {
return T.self
}
func foo() {
let my_var = SomeClass()
let some_prop = declmetatype(my_var.my_prop).init()
some_prop = my_var.my_prop + 1
}
In foo() above, some_prop is of type SomeVeryLongTypeName (which, here, is simply Int), which due to Swift's static typing is naturally known at compile time.
Note, however, that in Swift we cannot use this technique to only declare types, but must also instantiate them. Moreover, there's no concept of "default initializers" in Swift (as compared to default CTOR:s in C++), hence the need to constrain the generic typeholder in declmetatype(...) to a protocol of our own, where we provide a blueprint to some initializer we'd like to use in a "default sense" from the metatype.
We may visit the Language Reference - Types - Metatypes for additional details on metatypes, particularly:
Use an initializer expression to construct an instance of a type
from that type’s metatype value. For class instances, the initializer
that’s called must be marked with the required keyword or the entire
class marked with the final keyword.
Where I've emphasized the available use of metatypes to construct instances of types (as shown above), which does not, however, cover using metatypes to only declare types.