11

I've never used std::get_if, and since its name is different from std::get, I don't see a reason why its argument should be a pointer¹ (whereas std::get has a by-reference parameter).


¹If it was named std::get too, then overload resolution would be a reason enough.


Yes, my question could be duped to the question Is it absolutely necessary for std::any_cast() and std::get_if(std::variant) to take pointer as an argument?, but the point is that there's no answer there that addresses std::get_if vs std::get, just one comment; the only answer concentrates on std::any_cast.

Enlico
  • 23,259
  • 6
  • 48
  • 102
  • I seem to recall Jason Turner talking about why that is in one of the C++ Weekly videos. – WBuck Sep 21 '21 at 14:45
  • Does this answer your question? [Is it absolutely necessary for std::any\_cast() and std::get\_if(std::variant) to take pointer as an argument?](https://stackoverflow.com/questions/38617907/is-it-absolutely-necessary-for-stdany-cast-and-stdget-ifstdvariant-to) – xskxzr Sep 22 '21 at 03:29
  • 1
    @xskxzr, no, for the reason I've added in the question. – Enlico Sep 22 '21 at 05:22

3 Answers3

15

This is because get_if is noexcept, so an exception will never be thrown. In order to achieve this, it must return a pointer so that nullptr can be returned when the access fails.

Because it returned the pointer, it must take the pointer of the variant. If it takes the reference of variant, then it must be able to accept the type of variant&, const variant&, variant&& and const variant&&, but it does not make sense for the pointer to remain ref-qualified.

Considering that get_if accepts variant&&, what you do is return the address of an xvalue, which is terrible. Even if get_if only allows variant& and const variant&, the latter can still accept a variant&& and return a dangling.

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
4

From what I can tell, it is based off dynamic cast logic. The dynamic cast that can fail takes a pointer and returns a pointer.

Similarly, get that can fail takes a pointer and returns one.

But really it looks like a tiny bikeshed decision of not much importance.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
1

This design allows you to apply "chained" invocations like this:

struct A : public std::variant<int, float>{};

int main()
{
    std::variant<A, char> f;
    A a;
    static_cast<std::variant<int, float>&>(a) = 10;
    f = a;
    cout << *std::get_if<int>(std::get_if<A>(&f));
    return 0;
}
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Alex Aparin
  • 4,393
  • 5
  • 25
  • 51