一般开始,加上decltype考虑本地使用声明 [英] Beginning generically, plus decltype considering local using-declaration

查看:133
本文介绍了一般开始,加上decltype考虑本地使用声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++ 0x的范围循环有一个特殊的异常处理数组(FDIS§6.5.4),并有两个函数,std :: begin和end,它们被重载处理数组或选择begin /结束方法。这使我相信接受一个通用序列的函数可以被编写以匹配一个范围for循环的行为:

C++0x's ranged-for loop has a special exception to handle arrays (FDIS §6.5.4), and there are two functions, std::begin and end, which are overloaded to handle arrays or to select begin/end methods. This leads me to believe a function accepting a generic sequence could be written to match a ranged-for loop's behavior:

template<class C>
void f(C &c) {
  using std::begin;
  using std::end;
  do_something_with(begin(c), end(c));
}



如果C的命名空间中有一个更具体的开始/它将通过ADL选择,否则代码defaults到std :: begin / end。

If there's a "more specific" begin/end in the namespace of C, it will be selected through ADL, otherwise the code "defaults" to std::begin/end.

但是,有一个原因的范围 - 有特殊的异常。如果在带有指针的语义不同的begin / end的命名空间中传递类型的数组,则不选择std :: begin / end的数组形式:

However, there is a reason ranged-for has that special exception. If passing an array of a type in a namespace with a semantically-different begin/end which takes a pointer, the array forms of std::begin/end aren't selected:

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!
}

为了避免这种情况,结束包装器(它在内部使用ADL)并明确地调用它们而不是std :: begin或ADLized begin?

To to avoid this, is there a better solution than writing my own begin/end wrappers (which use ADL internally) and calling them explicitly instead of either std::begin or an 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));
}

但是,如上面的省略号所示,我甚至不知道写我的::开始!我如何为那个decltype选择将通过本地使用声明和ADL选择的类型?

However, as shown by the ellipsis above, I don't even know how to write my::begin! How can I, for that decltype, select the type that will be selected through a local using-declaration and ADL?

推荐答案

I在使用元组时遇到相同的情况:

I've encountered the same situation while using tuples:

template<typename Tuple>
auto f(Tuple&& tuple)
-> /* ??? */
{
    using std::get;
    return get<Idx>(tuple);
}

接受 std :: tuple boost :: tuple ,并接受lvalue和rvalues,而不是 template< typename ... Types& auto f(std :: tuple< Types ...>& tuple) - > / * ???

which accepts both std::tuple and boost::tuple, and accepts both lvalues and rvalues as opposed to template<typename... Types> auto f(std::tuple<Types...>& tuple) -> /* ??? */.

这个特殊情况是由一个traits类解决的,这实际上是由标准提供的: std :: tuple_element 。像traits类一样,这个想法是 tuple 是一个协议,任何想要符合它的将提供一个专门的例如。 tuple_element 。所以在我的情况下,解决方案已经存在。

This particular case was solved with a traits class, which is in fact provided by the Standard: std::tuple_element. As usual with traits classes, the idea is that tuple is a protocol and anything that want to conform to it will provide a specialization for e.g. tuple_element. So in my case the solution already existed.

在你的情况下,如果你正在写一个库,我建议写这样的traits类(和记录)。在应用程序代码或其他情况下,我不太确定。

In your case, if you were writing a library, I'd recommend writing (and documenting) such a traits class. In application code or other situations, I'm not so sure.

这篇关于一般开始,加上decltype考虑本地使用声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆