this post was submitted on 15 Jul 2023
11 points (100.0% liked)

C++

1763 readers
1 users here now

The center for all discussion and news regarding C++.

Rules

founded 1 year ago
MODERATORS
 

Since c++11 it has been possible that instead of declaring your function as "int name(arguments);" you can now do "auto name(arguments) -> int;". The place I work at has it as style rule that all functions need to be declared that way. Now obviously this is not that large of a thing, and a consistent style is more important than my opinion here. But this has always felt like a weird thing, adding extra bloat to reading code. Anyways looking around I saw some positives to this construction, generally with the use of long return types, that are paramount when using templates. Here the benefit is that the function name is not hidden behind multiple template declarations, which does seem like a good argument. Also lamndbas generally use this. However I personally see some negatives here with using this foe every function, namely:

  • extra bloat when typing/reading the code. This however could be automated to switch between the needed representations. It currently isent so I personally have ti type the auto and trailing return type manually, its not a lot, but still. Also reading code has become a bit more annoying if you have a lot of function overrides as you now have to first look which block of declarations have the smae function name and then parse which one has the correct return type.
  • inconsistency with other typed programming languages: This one is probably why it irks me, but (and correct me on this) I dont know of a c style typed programming language that supports this type of syntax. Python has typehints(which you should use, please), which are declared after the function, and I remember Haskell also has their return type after the function name. But both of thede languages serve a different function than c++. More similar languages like c# and java dont support trailing return types.

Anyway enough of me ranting, I would like to know wath the other opinions here are. And whether this rant is missing se important arguments?

you are viewing a single comment's thread
view the rest of the comments
[โ€“] [email protected] 2 points 1 year ago (1 children)

I don't use it myself, but I don't have a strong opinion on that. My beef if with deduced return types, especially with templates. It is typical in modern C++ code to see such function:

template<typename ~whatever~>
auto foo(~some arguments which types are deduced from nested templated conditional using declarations that you don't understand~) {
    return ~call to other template function that's 10 levels deep and is also conditional on properties of template parameters with some ifdefs for fun~;
}

That makes it absolutely impossible to figure out what types function takes as parameters and what type it returns until you hit 10-page compiler error that will explain everything (which is also will force you to read through implementation details of this function to figure out how to fix it). And often IDEs can't help you either.

[โ€“] [email protected] 1 points 1 year ago

But what about something like this?

template<typename T>
auto make_foo(T&& foo_arg) {
    return foo<std::decay_t<T>>{std::forward<T>(foo_arg)};
}

This is exactly the pathological case you gave as example, but I find this extremely readable. Specifying the return type would actually not help at all and the pattern the easily recognizable in the end.

If your naming is bad, arguments not clear, and implementation not recognizable and hard to infer what it's doing then that's a totally different problem and I would say trailing return type and deduced return type is the least of my concerns.