3 ms·
1. In a world without templates/generics, you have to manually define a different such struct for every possible return type. Can be macro'd at the function def
by GeneralMayhem 3y ago
1. In a world without templates/generics, you have to manually define a different such struct for every possible return type. Can be macro'd at the function definition, but it's ugly.
2. Without first-class support, it's very difficult to assert that the error is actually being checked. Consider:
int someVal = getSomeVal(...).v;
doSomethingWith(someVal);
vs.
(int someVal, error e) = getSomeVal(...);
doSomethingWith(someVal);
Which is easier to catch at code-review time, or even at linter time?
In most languages that don't support multiple return values, both problems are solvable with templates or local equivalent - see, for instance, absl::StatusOr for C++ (https://abseil.io/docs/cpp/guides/status https://abseil.io/docs/cpp/guides/status).
- signa11 3y ago> 1. In a world without templates/generics, you have to manually define a different such struct for every possible return type. Can be macro'd at the function definition, but it's ugly. one trivial possibility/option is to define in-out parameters, and just return errors: <error-type/int/…> foo(T*, <params>) will that not be ok ?
- 0x09 3y ago>Can be macro'd at the function definition, but it's ugly. I wonder if typeof in c23 has changed this at all. Previously there was no sense in defining an anonymous struct as a function's return type. You could do it, but those structs would not be compatible with anything. With typeof maybe that's no longer the case. e.g. with clang 16 and gcc 13 at least this compiles with no warning and g() returns 3. But I'm not sure if this is intended by the standard or just happens to work. struct { int a; int b; } f() { return (typeof(f())){1,2}; } int g() { typeof(f()) x = f(); return x.a + x.b; } edit: though I suppose this just pushes the problem onto callers, since every function that does this now has a distinct return type that can only be referenced using typeof(yourfn).
- kaashif 3y agoI think most of the time people really want a sum type, NOT a tuple. i.e. you can get back either a value OR an error, but not both. In Go, there's the pattern of returning nil, err, which is a hint that we really want a sum type there. > In most languages that don't support multiple return values, both problems are solvable with templates or local equivalent I don't really see the difference between tuples in C++ and multiple return values in Go (since you cite C++ as a language that doesn't have multiple return values). val, err := do_something() or auto [val, err] = do_something(); What's the real difference there? Syntactic sugar?
- GeneralMayhem 3y agoI agree, you really want a sum, not a tuple - that's why my example was absl::StatusOr<T>, not std::pair. But a tuple plus tooling support (e.g., linters in Go that don't allow you to not use the returned error value) can emulate a sum type.