从元组中获取元素
getting an element from a tuple
可能重复:
为什么不';ADL找不到功能模板?
调用get
似乎不会调用依赖于参数的查找:
auto t = std::make_tuple(false, false, true);
bool a = get<0>(t); // error
bool b = std::get<0>(t); // okay
g++4.6.0表示:
error: 'get' was not declared in this scope
Visual Studio 2010表示:
error C2065: 'get': undeclared identifier
为什么?
这是因为您试图通过提供0
作为模板参数来显式地实例化get
函数模板。在模板的情况下,如果具有该名称的函数模板在调用点可见,ADL就会工作。这个可见的函数模板只帮助触发ADL(实际上可能不会使用(,然后,可以在其他命名空间中找到最佳匹配。
请注意,触发(或启用(ADL的功能模板不需要定义:
namespace M
{
struct S{};
template<int N, typename T>
void get(T) {}
}
namespace N
{
template<typename T>
void get(T); //no need to provide definition
// as far as enabling ADL is concerned!
}
void f(M::S s)
{
get<0>(s); //doesn't work - name `get` is not visible here
}
void g(M::S s)
{
using N::get; //enable ADL
get<0>(s); //calls M::get
}
在g()
中,名称N::get
在调用get<0>(s)
时触发ADL。
演示:http://ideone.com/83WOW
C++(2003(第14.8.1/6节内容如下:
[注意:对于简单的函数名称,即使函数名称在调用范围内不可见,也会应用依赖于参数的查找(3.4.2(。这是因为调用仍然具有函数调用的语法形式(3.4.1.(。但是,当使用具有显式模板参数的函数模板时,除非在调用时存在具有该名称的函数模板,否则调用不会具有正确的语法形式。如果没有这样的名称可见,则该调用的语法格式不正确,并且不应用依赖于参数的查找如果某个这样的名称可见,则应用依赖于参数的查找,并且可能在其他命名空间中找到其他函数模板。
[示例:
namespace A { struct B { }; template<int X> void f(B); } namespace C { template<class T> void f(T t); } void g(A::B b) { f<3>(b); //ill-formed: not a function call A::f<3>(b); //well-formed C::f<3>(b); //ill-formed; argument dependent lookup // applies only to unqualified names using C::f; f<3>(b); //well-formed because C::f is visible; then // A::f is found by argument dependent lookup }
--结束示例]-结束注释]
ADL不直接应用于模板id,如get<0>
,因此编译器不会真正从该路径启动。C++11§14.8.1/8(在C++03,14.8.1/6中(:
[注意:对于简单的函数名称,即使函数名称在调用范围内不可见,也会应用依赖于参数的查找(3.4.2(。这是因为调用仍然具有函数调用的语法形式(3.4.1.(。但是,当使用具有显式模板参数的函数模板时,调用不具有正确的语法形式,除非在调用时存在具有该名称的函数模板。如果没有这样的名称可见,则该调用的语法格式不正确,并且不应用依赖于参数的查找。如果某个这样的名称可见,则应用依赖于参数的查找,并且可能在其他命名空间中找到其他函数模板。
它接着举了一个简短的例子。所以解决方法很简单:
#include <tuple>
template< typename > // BEGIN STUPID BUT HARMLESS HACK
void get( struct not_used_for_anything ); // END STUPIDITY
auto t = std::make_tuple(false, false, true);
bool a = get<0>(t); // Now the compiler knows to use ADL!
bool b = std::get<0>(t); // okay
http://ideone.com/fb8Ai
注意,上述not_used_for_anything
仅仅是一种安全机制。它旨在成为一个从未完成的不完整类型。省略它也可以,但不安全,因为它可能会与您想要的签名冲突。
template< typename >
void get() = delete;
http://ideone.com/WwF2y
注:标准中的上述引用是非规范性的,这意味着在委员会看来,我们可以在没有解释的情况下理解这一点,因为它是由语言和语法的其余部分暗示的,特别是3.4.2中没有提到查找模板id。是的,对!
- 对于set上的循环-获取next元素迭代器
- 在 alglib::real_1d_array 中获取元素总和的奇怪错误
- 如何在 c++ stl 中获取列表中被推回的元素的地址,在常量时间内?
- push_back通过自行创建的对象获取最后一个元素的向量
- 从自定义类获取对象向量中的 max 元素
- 从 c++ 中的链表中获取元素
- 比较它们之间的元素并获取公共值的键
- 获取指向指针的指针元素 (c++)
- CPtrList - 如何获取元素的索引?
- 如何从一个容器中获取某些元素并将其转换插入到另一个容器中?
- 获取结构 c++ 中元素的索引
- 如何获取指针数组中的元素数量?
- 在std::集中获取与给定元素最接近的元素
- 无法获取已填充堆栈<char>的顶部元素
- 检查HTML 5视频元素是否正在获取帧
- 有没有函数可以直接获取 std::vector 元素的大小?
- 从矢量的元素获取指针
- 从 /dev/sd* 元素获取 /dev/disk/by-id 元素
- 2d查找重复元素/获取索引位置并计数重复项
- 为什么来自 rvalued-stl-container 的元素获取者返回左值