LB--/utf

Change pair to struct with named members

LB-- opened this issue · 4 comments

mosra commented

Interesting discussion point.

In my APIs I prefer pair/tuple over struct because std::tie() can be used on it and then I can name, reorder or retype the members as I like. That makes of course sense only if it is clear which member is which (e.g. it's either intuitively clear or the types are different that there is no possibility in mixing them up). Another point is that when using std::tie() the return type is basically anonymous set of other types, which makes the API surface area smaller -- no need to document yet another trivial struct.

On the other hand, std::*map::insert()'s return type (or its behavior in general) is just bad. I am angry every time I come across it.

LB-- commented

I agree about std::tie, and I've been wondering if there is a way to keep it working for custom structures using some boilerplate or something.

mosra commented

Structured bindings in C++17 should solve that.

Otherwise, I think that maybe just a conversion operator could do it?

#include <tuple>

struct MyReturnType {
    void* a; int b; double c;

    operator std::tuple<void*&, int&, double&>() { return std::tie(a, b, c); }
};

std::tuple<void*, int, double> foo1() { return std::make_tuple(nullptr, 3, 1.27); }
MyReturnType foo2() { return {nullptr, 3, 1.27}; }

int main() {
    void* first;
    int second;
    double third;
    std::tie(first, second, third) = foo1();
    std::tie(first, second, third) = foo2();
}

I tried to make the conversion operator const and return just a standard tuple, but neither Clang nor GCC wanted to eat it.

mosra commented

Funny that in this case foo2() combines the advantages of both, usable with std::tie() and without the annoying std::make_tuple call needed pre-C++17 because the tuple constructor is explicit.