Apparently Haskell supports overloading on return type: https://stackoverflow.com/a/442291/
Apparently Haskell supports overloading on return type: https://stackoverflow.com/a/442291/
I don't think this is even significantly more code than a Haskell version would be, and the error messages and limitations are not significantly worse either.
Error messages for missing/ambigous overloads are necessarily nasty when there are many candidate overloads. And it is obvious that return-type overloading is not usable in situations where the desired return type is not known, as in the auto example.
As for the template error messages, since this is just one layer of templates, I suspect that they will be quite decent - especially considering that even one std::string-related error message is easily a few lines of almost completely irrelevant gibberish (does anyone actually use non-default char_traits???).
I am a bit confused here, are you talking about something that would require templates in C++?
template <T>
auto func(T t) { return t; }
y = func<int>(5);Here is the gist of it. Inferring types in C++ (and languages with type deduction) basically looks like this:
auto a = something;
Here, the type of a is determined by the type of something. The left hand side determines the type of the right hand side.In Rust (and languages with type inference), inferring types can look like that:
let a = something;
but it can also "go backwards": let a = 5;
let b: u64 = a;
Here, a will be a u64, because you later assign it to something of type u64, and so the compiler can "work backwards" to infer this. (In my understanding, it does not literally work backwards, but it feels like it.)To see how this plays out in your parent's comment, I adapted the code from: https://docs.microsoft.com/en-us/cpp/cpp/auto-cpp?view=vs-20...
#include<vector>
void func(std::vector<int> &vect)
{
vect.push_back(30);
}
int main()
{
std::vector<int> vect;
vect.push_back(10);
vect.push_back(20);
func(vect);
return 0;
}
You can't say "auto vect;" there, or else gcc will say "error: declaration of 'auto vect' has no initializer".But in Rust, you can write:
fn func(vect: &mut Vec<i32>) {
vect.push(30);
}
fn main() {
let mut vect = Vec::new();
vect.push(10);
vect.push(20);
func(&mut vect);
}
no type annotation on "let mut vect" there; it can see that you eventually pass it to func, and that's enough to infer the type. (For completeness, the line would be "let mut vect: Vec<i32> = Vec::new();" if you wrote out the type. use std::collections::HashMap;
fn main() {
let mut foo = HashMap::new();
foo.insert("bar", 42);
}
In C++, the declaration of `foo` would require a type annotation like `map<string_view, int>`. fn main() {
foo((42));
foo((12.0, 13.0));
}
pub fn foo(args: impl FooArgs) { args.exec() }
pub trait FooArgs { fn exec(self); }
impl FooArgs for u32 { fn exec(self) { println!("A number: {}", self) } }
impl FooArgs for (f32, f32) { fn exec(self) { println!("{} x {} = {}", self.0, self.1, self.0 * self.1) } }
https://play.rust-lang.org/?version=stable&mode=debug&editio... A number: 42
12 x 13 = 156
Usually you won't abuse tuples quite like this, but it's an option. The same pattern of using traits - without the tuples - is more common [1]. Or if you need variadic functions, typically you'd resort to a macro instead.[1]: https://medium.com/@jreem/advanced-rust-using-traits-for-arg...
fn Default<T>::default() -> T
? Which is polymorphism, not overloading? Idk. Maybe I’m just being pedantic?Ada does too.
Found a good source eventually: https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Devel...