I saw this code. Can you explain me, whats mean this piece of code:
auto main() ->
{
}
What is difference between this and follow code:
int main()
{
return 0;
}
auto main() is illegal in as per the resolution of core issue 1669.
The intent of whatever person gave you that code was probably to use return type deduction to figure out the return type. This happens in C++11 lambdas, and is being extended to most functions (main being one exception) in C++14.
Related
Lets take the following Golang expressions :
type MyStruct struct {
foo int,
bar map[string]MyInterface
}
type MyInterface interface { /* ... */ }
func firstFunc() { /* ...*/ }
func secondFunc() { /* ...*/ }
with the following builder function :
func NewMyStruct() *MyStruct {
// Building a map made of only static content, known at compile time
// Assigning it to a local variable
m := map[string]MyInterface {
"first": firstFunc,
"second": secondFunc,
}
/* ... */
return &MyStruct{
bar: m, // Copying the map into the struct field
/* ... */
}
}
I came across this code and decided to try optimizing it in terms of memory management and/or execution time.
Coming from the C++ world, I am used to the "static vs dynamic allocation" dilema and the use of constexpr. I am trying to achieve the same goal here in Golang: avoid constructing/allocating a data structure too often in the limits of what the language permits.
Question 1: In NewMyStruct(), is the temporary map effectively assigned to m constructed/allocated at each call?
Question 2: Can the compiler detect that the temporary map is made of static content, and construct it once for all?
My other solution is to go for a globally defined map and refer to it from the MyStruct instances using a pointer.
As Volker suggests, this is almost certainly premature optimization. However, if you've already found that this has some significant time cost in your program and are just looking for options, this Playground link shows a way to construct a map at program startup time and share it. The essence is just:
return &MyStruct{bar: sharedMap, /*...*/}
The shared map needs to be created by this point. If a simple static init is not possible, use an init function, or add a sync.Once to construct the map only once on the first call to your New function.
Consider this example in Go language:
type I interface {
get() string
}
type S struct {}
func (s *S) get() string {
return "here!"
}
var sSupplier = func() *S {
return &S{}
}
func foo(supplier func () I) {
i := supplier()
println(i)
}
func main() {
foo(sSupplier) // compile error, type mismatch
}
Type S inherit interface I. But apparently type func () *S does not inherit func () I, so I cannot call foo with sSupplier in place of the supplier function. Is there a way to fix it without forcing sSupplier to return type I?
In java you can use generics to do something like <T extends I> void foo(Supplier<T> supplier) {...} then call foo(sSupplier); with Supplier<S> sSupplier type. I'm not sure if similar approach is possible in go?
If you think for a bit about what generics do for you, they are really a way to ask the compiler to compile, on the spot, an anonymous wrapper function or lambda or whatever is needed to map from some concrete type. That is, given something like (I'll use C++ syntax here rather than Java as I'm much more familiar with C++):
template<T>
void f(T obj) {
// do stuff with the object
}
you're telling the compiler that when it sees f(int_value) it should build a function f that takes an int, and when it sees f(struct S) it should build a function f that takes a struct S, and so on. (This is a bit more natural in Java than it is in C++'s C underpinnings since Java does the whole argument-matching thing to decide which of these various f functions to call.)
In effect, instead of writing the actual function, you write a template—hence the C++ keyword—that the compiler can use to, at compile time, produce the function you really wanted. Since Go lacks generics, it lacks this sort of template-expansion trick.
That leaves you with several obvious alternatives, though. One is exemplified by go:generate (see, e.g., Explain go generate in this example). In this particularly simple case, though, you can just write the expansion yourself in line:
foo(func() I { return sSupplier() })
See a more complete example on the Go playground. I replacd your println(i) with fmt.Printf("%#v\n", i) to print the interface object's value in a slightly more useful form.
I am trying to use recursive lambda functions with auto keyword as below.
#include <iostream>
using namespace std;
int main()
{
auto func = []()->void{
static int x = 0;
cout << x << endl;
if (x < 5) {
func();
x++;
}
};
func();
return 0;
}
But it is throwing compiler error as below.
main.cpp: In lambda function:
main.cpp:19:13: error: use of ‘func’ before deduction of ‘auto’
func();
^~~~
I understood that we can achieve the same with std::function. But I wanted to know why I am getting error by using 'auto'.
I went through below stack overflow questions.
Can lambda functions be recursive?
Recursive lambda functions in C++11
Use of 'auto func(int)' before deduction of 'auto' in C++14
But I couldn't figure out why auto with lambda is throwing error in this case. Can anyone please let me know why I am getting this error?
The problem is not the return-type of the lambda expression. The problem is the type of the lambda itself.
Each lambda expression is a unique anonymous type.
In your code, the compiler knows that the lambda returns void, but it doesn't yet know the type of the lambda, since it has not fully parsed it yet.
To give a counter example to highlight the issue.
#include <iostream>
int main()
{
int x;
auto func = [&](){
// func is going to become an int here, but the compiler does not know that yet
// it has to parse the whole expression first.
x = func;
return 5;
}(); // <-- calling the lambda and assigning the return value to func
}
You cannot make lambda recursive. Lambdas cannot be recursive because they don't have a name. See this: https://en.cppreference.com/w/cpp/language/lambda
an unnamed function object capable of capturing variables in scope.
Here lambda generate before initialization, thus the compiler gives you an error.
The only way to implement it in real lambda calculus is to use Y combinator. But I think that's meaningless in C++. Especially here you are not using enclosure at all.
In C++, there's another way to implement it: use std::function to replace auto, and then call the std::function rather than lambda instead.
I am trying to interface with some C code from Go. Using cgo, this has been relatively straight-forward until I hit this (fairly common) case: needing to pass a pointer to a structure that itself contains a pointer to some data. I cannot seem to figure out how to do this from Go without resorting to putting the creation of the structure into the C code itself, which I'd prefer not to do. Here is a snippet that illustrates the problem:
package main
// typedef struct {
// int size;
// void *data;
// } info;
//
// void test(info *infoPtr) {
// // Do something here...
// }
import "C"
import "unsafe"
func main() {
var data uint8 = 5
info := &C.info{size: C.int(unsafe.Sizeof(data)), data: unsafe.Pointer(&data)}
C.test(info)
}
While this compiles fine, trying to run it results in:
panic: runtime error: cgo argument has Go pointer to Go pointer
In my case, the data being passed to the C call doesn't persist past the call (i.e. the C code in question digs into the structure, copies what it needs, then returns).
See "Passing pointers" section in cgo docs:
Go code may pass a Go pointer to C provided the Go memory to which it points does not contain any Go pointers.
And also:
These rules are checked dynamically at runtime. The checking is controlled by the cgocheck setting of the GODEBUG environment variable. The default setting is GODEBUG=cgocheck=1, which implements reasonably cheap dynamic checks. These checks may be disabled entirely using GODEBUG=cgocheck=0. Complete checking of pointer handling, at some cost in run time, is available via GODEBUG=cgocheck=2.
If you run the snippet you've provided with:
GODEBUG=cgocheck=0 go run snippet.go
Then there is no panic. However, the correct way to go is to use C.malloc (or obtain a "C pointer" from somewhere else):
package main
// #include <stdlib.h>
// typedef struct {
// int size;
// void *data;
// } info;
//
// void test(info *infoPtr) {
// // Do something here...
// }
import "C"
import "unsafe"
func main() {
var data uint8 = 5
cdata := C.malloc(C.size_t(unsafe.Sizeof(data)))
*(*C.char)(cdata) = C.char(data)
defer C.free(cdata)
info := &C.info{size: C.int(unsafe.Sizeof(data)), data: cdata}
C.test(info)
}
It works because while regular Go pointers are not allowed, C.malloc returns a "C pointer":
Go pointer means a pointer to memory allocated by Go (such as by using the & operator or calling the predefined new function) and the term C pointer means a pointer to memory allocated by C (such as by a call to C.malloc). Whether a pointer is a Go pointer or a C pointer is a dynamic property determined by how the memory was allocated.
Note that you need to include stdlib.h to use C.free.
Sorry for the ambiguous title.
I'm reading this book http://algs4.cs.princeton.edu/home/ and I thought it would be good to implement the examples in Go as a learning exercise, however the book uses Java as its language to describe code in.
One of the first chapters discusses setting up some core datatypes/container style classes to re-use later on but I'm having trouble trying to hammer these into a Go setting, mainly because these datatypes seem to be enjoying the use of Java generics.
For example, I've written the following code
package bag
type T interface{}
type Bag []T
func (a *Bag) Add(t T) {
*a = append(*a, t)
}
func (a *Bag) IsEmpty() bool {
return len(*a) == 0
}
func (a *Bag) Size() int {
return len(*a)
}
This works in principle in the sense that I can add items to a Bag and check its size and everything. However this also means that the following code is legal
a := make(bag.Bag,0,0)
a.Add(1)
a.Add("Hello world!")
a.Add(5.6)
a.Add(time.Now())
I was just wondering if there was any way of enforcing the type so it conforms to a contract similar to
Bag<T> bagOfMyType = new Bag<T>()
e.g.
Bag<Integer> bagOfInts = new Bag<Integer>()
I know Go doesn't have generics and they're not really The Go Way, but I was just wondering if it is a possible to "enforce" anything at compile time (probably not)
Sorry for the long post
EDIT: OK so I've been looking into this a little further, I've pretty much given up with the generics side of things (I understand this is not on the roadmap for Go) so I'm thinking of doing something similar to Haskell typeclasses with interfaces, e.g.
type T interface{}
type Bag interface {
Add(t T)
IsEmpty() bool
Size() int
}
type IntSlice []int
func (i *IntSlice) Add(t T) {
*i = append(*i, t.(int)) // will throw runtime exception if user attempts to add anything other than int
}
func (i *IntSlice) IsEmpty() bool {
return len(*i) == 0
}
func (i *IntSlice) Size() int {
return len(*i)
}
The problem with this is the type enforcement is only enforced at runtime.
Anyone got any ideas how to improve on this?
I'm new to Go myself, so I'm curious if someone will have a better answer, but here's how I see it:
You want compile-time enforcement that when Add() is called on an IntSlice, its parameter is an int. Well, here's how you do that:
func (i *IntSlice) Add(t int) {
*i = append(*i, t)
}
Since there aren't generics, the Add() method is going to be different for every type of Bag, so the Bag interface, assuming you need it, becomes just:
type Bag interface {
IsEmpty() bool
Size() int
}
That makes sense to me, because you can't pass a Bag around and throw just anything in it. Knowing that something is a Bag isn't enough to know how to call Add() on it; you must know what type of Bag you're dealing with.
You could make the interface specific to the type, like IntBag, but since only one type is actually going to satisfy that interface, you might as well get rid of the interface and change the name of IntSlice to IntBag.
Basically that means giving up entirely on anything generic-like, and just creating a type with some methods that do what you want:
type IntBag []int
func (b *IntBag) Add(i int) {
*b = append(*b, i)
}
func (b IntBag) IsEmpty() bool {
return len(b) == 0
}
func (b IntBag) Size() int {
return len(b)
}
Update: Sometimes generics really would come in handy. It seems to me we're left choosing on a case-by-case basis what exactly is best for a given problem. With empty interfaces and reflection, you can get some generic-like behavior, but it tends to be ugly and you give up some compile-time type checking. Or you give up on generics and have some code-duplication. Or you just do it a totally different way.
I asked a question a few weeks ago about how I should use Go to handle problems that look to me like they need class hierarchies. The answer was basically that there is no general solution; it's all case-by-case. I think the same applies for generics: there are no generics in Go, and there's no general solution for translating generics-based solutions to Go.
There are many cases where you might use generics in another language but interfaces are perfectly adequate (or truly shine) in Go. Your example here is one where interfaces aren't really a proper replacement. See also: Go Vs. Generics.
I'm pretty well-versed with Go. Generics are a hotly-debated topic, and there is currently nothing analogous to Java generics or C++ templates. The convention at the moment is to implement a "generic" type with an empty interface and then wrap it with a specific type implementation that makes sure only elements of that type are used. Here's an example with container/list from the Go standard library.
http://play.golang.org/p/9w9H1EPHKR
package main
import (
"container/list"
"fmt"
)
type IntList struct {
innerList *list.List
}
func NewIntList() *IntList {
return &IntList{list.New()}
}
func (l *IntList) Add(i int) {
// this is the only way to add an element to the list,
// and the Add() method only takes ints, so only ints
// can be added
l.innerList.PushBack(i)
}
func (l *IntList) Last() int {
lastElem := l.innerList.Back()
// We can safely type-assert to an int, because Add()
// guarantees that we can't put a non-int into our list
return lastElem.Value.(int)
}
func main() {
l := NewIntList()
l.Add(5)
l.Add(4)
l.Add(3)
l.Add(2)
l.Add(1)
fmt.Println("Expecting 1; got:", l.Last())
}