10

Can anyone tell me why std::get<T> of C++17 is a global function and not a member-function of variant<...>?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Bonita Montero
  • 2,817
  • 9
  • 22

1 Answers1

9

If get<T>() were a member function template, a template keyword would be needed when it is called in a dependent context. For example:

template <typename Variant>
void f(Variant const& v) {
    auto x0 = v.template get<T>(); // if it were a member
    auto x1 = get<T>(v);           // using a non-member function
}

Even without a using declaration or directive get() is found as both std::variant<...> and get() are declared in namespace std. Thus, there seems to be no good reason to make it a member function as the global function is easier to use.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • 1
    Well, you need a function template named `get` in scope for `get(v)` to be parsed correctly. Still, better than having to write `template` at every turn. – T.C. Feb 06 '17 at 10:17
  • @T.C.: good point - with the template parameter it isn't directly found via ADL. That may argue for an uncallable function template being declared at global scope (e.g., `template typename T::uncallable get();`; the number of arguments don't really matter...). – Dietmar Kühl Feb 06 '17 at 10:46
  • 2
    Why is `emplace()` a member then? That doesn't seem to need the `template` keyword: https://en.cppreference.com/w/cpp/utility/variant/emplace – ShdNx Oct 21 '19 at 21:40
  • 2
    @ShdNx: the problem is with parsing member function templates with explicitly specified template arguments: while `get(v)` inherently requires that `T` gets specified, `v.emplace(a...)` desuces all its template parameters. Hence, the problem doesn’t exist over there. – Dietmar Kühl Oct 22 '19 at 12:56
  • 2
    @DietmarKühl: actually, you need to explicitly specify `T` for `emplace`, otherwise it doesn't know what to try to construct from the arguments given. See my earlier link to cppreference.com for examples. – ShdNx Oct 22 '19 at 17:42
  • @ShdNx: interesting - I didn’t realize that `std::variant::emplace` also takes an explicit template argument. Of course, that means that you’ll need to write `v.template emplace(a...)` in contexts where `v`’s type is a template parameter. The implication is that the designers of `std::variant` assumed that `emplace` is normally used on objects with a non-dependent name. – Dietmar Kühl Oct 24 '19 at 18:15