Fre*_*urk 11 c++ templates argument-dependent-lookup c++11
C++ 0x的ranged-for循环有一个处理数组的特殊异常(FDIS§6.5.4),并且有两个函数std :: begin和end,它们被重载以处理数组或选择开始/结束方法.这使我相信可以编写接受通用序列的函数来匹配ranged-for循环的行为:
template<class C>
void f(C &c) {
using std::begin;
using std::end;
do_something_with(begin(c), end(c));
}
Run Code Online (Sandbox Code Playgroud)
如果在C的命名空间中有一个"更具体"的开始/结束,它将通过ADL选择,否则代码"默认"为std :: begin/end.
但是,有一个原因,因为有特殊例外.如果在命名空间中传递一个类型的数组,其中一个语义不同的begin/end接受一个指针,则不会选择std :: begin/end的数组形式:
namespace ns {
struct A {};
void begin(A*); // Does something completely different from std::begin.
}
void f_A() { // Imagine above f() called with an array of ns::A objects.
ns::A c[42];
using std::begin;
begin(c); // Selects ns::begin, not array form of std::begin!
}
Run Code Online (Sandbox Code Playgroud)
为了避免这种情况,有没有比编写我自己的开始/结束包装器(内部使用ADL)并显式调用它们而不是std :: begin或ADLized begin更好的解决方案?
namespace my {
template<class T>
auto begin(T &c) // Also overload on T const &c, as std::begin does.
-> decltype(...) // See below.
{
using std::begin;
return begin(c);
}
template<class T, int N>
T* begin(T (&c)[N]) {
return c;
}
}
// my::end omitted, but it is analogous to my::begin.
template<class C>
void f(C &c) {
do_something_with(my::begin(c), my::end(c));
}
Run Code Online (Sandbox Code Playgroud)
但是,如上面的省略号所示,我甚至不知道怎么写我的:: begin!对于该decltype,我如何选择将通过本地using-declaration和ADL选择的类型?
我在使用元组时遇到了同样的情况:
template<typename Tuple>
auto f(Tuple&& tuple)
-> /* ??? */
{
using std::get;
return get<Idx>(tuple);
}
Run Code Online (Sandbox Code Playgroud)
它接受 和std::tuple
,boost::tuple
并且接受左值和右值,而不是template<typename... Types> auto f(std::tuple<Types...>& tuple) -> /* ??? */
。
这个特殊情况是通过一个特征类来解决的,它实际上是由标准提供的:std::tuple_element
。与通常的特征类一样,这个想法是,这tuple
是一个协议,任何想要遵守它的东西都会为例如提供专门化tuple_element
。所以就我而言,解决方案已经存在。
就您而言,如果您正在编写一个库,我建议您编写(并记录)这样一个特征类。在应用程序代码或其他情况下,我不太确定。
归档时间: |
|
查看次数: |
387 次 |
最近记录: |