为什么`variant`的`std::get<T>`是全局函数?

10

有人能告诉我为什么C++17的std::get<T>是全局函数,而不是variant<...>的成员函数吗?


9
我会提出一个补充问题:为什么它应该是一个成员函数? - Pete Becker
8
当然,与元组一样。语法变得太丑陋了。 - Baum mit Augen
1
@PeteBecker:可发现性、直觉性、与其他容器的一致性。 - Dwayne Robinson
1个回答

9
如果 get<T>() 是一个成员函数模板,在依赖上下文中调用时需要使用 template 关键字。例如:
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
}

即使没有using声明或指令,get()作为std::variant<...>get()在命名空间std中声明。因此,似乎没有充分的理由将其作为成员函数,因为全局函数更易于使用。

1
你需要在作用域中有一个名为 get 的函数模板,才能正确解析 get<T>(v)。不过,这仍然比每次都要写 template 要好。 - T.C.
@T.C.:好观点 - 使用模板参数时,它不会直接通过ADL找到。这可能支持在全局范围内声明一个不可调用的函数模板(例如,template <typename T> typename T::uncallable get();;实际上参数数量并不重要...)。 - Dietmar Kühl
2
为什么emplace()是成员函数呢?它似乎不需要template关键字:https://en.cppreference.com/w/cpp/utility/variant/emplace - ShdNx
2
@ShdNx:问题出在解析显式指定模板参数的成员函数模板上:虽然get<T>(v)需要明确指定T,但v.emplace(a...)则推导出所有的模板参数。因此,在这里问题并不存在。 - Dietmar Kühl
2
@DietmarKühl:实际上,您需要明确指定emplaceT,否则它不知道要尝试从给定的参数构造什么。请参阅我早期链接到cppreference.com的示例。 - ShdNx
@ShdNx:有趣 - 我没有意识到std::variant::emplace也需要一个显式的模板参数。当v的类型是一个模板参数时,在上下文中你需要写成v.template emplace<T>(a...)。这意味着std::variant的设计者们假设emplace通常用于具有非依赖名称的对象。 - Dietmar Kühl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接