手工制作的自动模板(不使用C ++ 0x)

时间:2010-09-05 19:33:37

标签: c++ templates c++11

如何在不使用c ++ 0x标准的情况下实现自动关键字功能?

for(std::deque<std::pair<int, int> >::iterator it = points.begin();
    it != points.end(); ++it)
{
   ...
}

也许这样的课程:

class AUTO
{
public:
   template <typename T1>
   AUTO(T1);

   template <typename T2>
   operator T2();
};

有了这样的用法:

for(AUTO it = points.begin(); it != points.end(); ++it)
{
   ...
}

但是,T1和T2是不同的。 如何将有关T1的信息移至运营商T2()? 真的有可能吗?

4 个答案:

答案 0 :(得分:12)

如果可以轻松实现库扩展,则不需要语言扩展。有关自动提案的详细信息,请参阅N1607

然而,article上的Boost.Foreach(您想要的那种)宏可能有助于理解与此类实施相关的问题。

  

什么是BOOST_FOREACH?

     

在C ++中,编写一个迭代的循环   一个序列是乏味的。我们可以   使用迭代器,需要一个   相当数量的锅炉板,   或者我们可以使用std :: for_each()   算法并将我们的循环体移动到   谓词,不需要少   锅炉板,迫使我们搬家   远离它将被使用的逻辑。   相比之下,其他一些语言,   像Perl一样,提供专用   “foreach”构造自动化   这个流程。 BOOST_FOREACH就是   这样的C ++构造。它迭代   为我们排序,让我们摆脱困境   必须直接处理迭代器   或写谓词。

     

BOOST_FOREACH是专为   易用性和效率。它没有   动态分配,没有虚拟   函数调用或调用   函数指针,不进行调用   这是不透明的   编译器的优化器。这导致了   接近最优的代码生成;该   BOOST_FOREACH的表现是   通常在百分之几的范围内   等效的手动编码循环。和   虽然BOOST_FOREACH是一个宏,但它   是一个非常乖巧的人。它   只评估一次参数,   导致没有令人讨厌的惊喜。

答案 1 :(得分:10)

有一个BOOST_AUTO宏或多或少地执行auto关键字...但是,看一下它的实现会告诉你找到一种使用C ++ 0x的方法要好得多:&gt;

答案 2 :(得分:3)

您可以使用这些宏以符合标准的方式解决此问题。

#define DEF_DED(D, E) any_base const & D = make_any_concrete((E))
#define DED(D, E) get_t(D, true ? ded_ty() : get_idt((E)))

template<typename T> struct id {
  typedef T type;
};

template<typename T>
id<T> get_idt(T t) { return id<T>(); }

struct any_base { };

template<typename D>
struct any_concrete : any_base {
  any_concrete(D d):d(d) {}
  mutable D d;
};

template<typename T>
any_concrete<T> make_any_concrete(T x) { return any_concrete<T>(x); }

struct ded_ty {
  template<typename T>
  operator id<T>() { return id<T>(); }
};

template<typename T>
T &get_t(any_base const &b, id<T>) { return static_cast<any_concrete<T> const&>(b).d; }

所以你的for循环成为

for(DEF_DED(it, points.begin()); 
    DED(it, points.begin()) != points.end(); 
  ++DED(it, points.begin()))
{
   ...
}

Eric Niebler将信用转到Conditional Love: FOREACH Redux。不确定这是否真的值得:)

答案 3 :(得分:2)

更直接的问题是从推导类型获取信息到数据成员声明。

class AUTO
{
public:
   template <typename T1>
   AUTO(T1);

   T1 state; // eg deque<...>::iterator - need this!
};

显然不会发生这种情况,因为必须在调用函数之前分配AUTO对象。

鉴于typeofdecltype,它并不是那么难。

#define AUTO( name, initializer ) typeof( initializer ) name = initializer

当然,这有很多限制。并typeof不标准。有了多个编译器支持,这可能是这些Boost工具的基础。