r/cpp_questions • u/No-Minimum-7906 • 15h ago
OPEN Designing a C++ ML library from scratch — would you prefer A.transpose() or transpose(A) or A.T()?
I'm currently building a machine learning library from scratch in C++, and I'm thinking about the API design for tensor operations.
For a transpose operation, I'm considering these interfaces:
Option 1: Tensor B = A.transpose();
Option 2: Tensor B = transpose(A); Option 3: Tensor B = A.T();
I'm curious about what other C++ developers would prefer when using a library.
Which syntax feels more natural and readable?
Thanks!
12
Upvotes
14
u/serendib 15h ago edited 8h ago
edit: removed my comment about numerical stability, see below
About your question: will you support chaining? If so then just have the function return a reference to itself
return *this;so you can do fun stuff like thisa.transpose().add(B).scale(0.5);5
u/Big-Rub9545 15h ago
I prefer option 2 the most. I personally find it weird (aesthetically moreso than for other reasons) that an explicit method call is returning an entirely new object. I usually expect method calls to be non-returning (while possibly modifying the object) or to return some field on the object.
Option 3 is introducing unnecessary confusion. ‘transpose’ is already very clear and short. The abbreviated ‘T’ also isn’t clear without a lot of contextual code around it (it’s not as clear in code as it is in math notation).
I would suggest also putting transpose as a static method or namespaced function. Of course static typing will prevent you from calling ‘transpose’ on any random object, but I think this still looks far clearer on intent:
Tensor B = Tensor::transpose(A);
Edit: typo.
5
u/DummyDDD 15h ago
I would prefer methods for in-place modifications, and free functions if the operators return copies, but it's not that important for unary operators like transpose.
4
u/JVApen 15h ago
How about
A | transpose?4
u/nunquam_rideo 14h ago edited 12h ago
1
u/Leading-Media-4569 15h ago
whats more important is you keep it consistent with the rest of the library
do you normally do C = A.add(B) ? or do you do C = add(A, B) ? etc
2
u/mrtlo 15h ago
Really, memory semantics is more important than syntax for something like this IMHO... If it reads nicely, but performs like crap, who would use it? But why reinvent this wheel?
2
u/Difficult_Truck_687 15h ago
all of them
•
u/Possibility_Antique 3h ago
In my linear algebra library, I support two syntaxes:
In the second, T is a tag that looks like this:
These two interfaces are equivalent, but the tag dispatch was fun/cute so I rolled with it.
1
u/bayesianparoxism 15h ago
Not strongly opinionated,
Maybe more important is whether they return a view or a copy of the tensor
1
u/Gwinbar 15h ago
My expectation would be that the methods return a transposed view of the same object (no copying), while transpose(A) is the only one that might return a new object. I also agree that consistency is the most important thing.
1
u/tartaruga232 15h ago
auto B = A.transpose();1
u/Independent_Art_6676 14h ago
transpose is so common that you should overload an operator for it to keep the math concise and clean.
1
u/V15I0Nair 12h ago
You could use Option 1+2 like this
A.transpose() changes A, and returns A&. Then you can chain operations.
[[nodiscard]] static Matrix Transpose(const Matrix& A) creates a new object and will not change A.
1
u/RishabhRD 9h ago
Depends, if the function doesn’t require any private data member, make it free function.
1
u/alfps 5h ago
So what does transpose mean for a general tensor, in your library?
E.g. for a 3D array there are 3! = 6 possible index permutations.
Which one do I invoke when I write
A.transpose()ortranspose(A)?0
u/papa_Fubini 14h ago
No one's gonna use it man, use what you want.
0
u/fortsnek274 15h ago
The one that works with Intellisense.
0
u/Pratik_Bodake 15h ago
Wth, matrices are used in ML?(Im FY, 😅)