Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handmade auto template (without using C++0x)

How can be realized the auto keyword functionality without using c++0x standard?

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

Maybe such class:

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

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

With such usage:

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

But, T1 and T2 are different. How to move info about T1 to operator T2()? Is it really possible?

like image 307
k06a Avatar asked Sep 05 '10 19:09

k06a


3 Answers

If a library extension was easily implementable there would have been no need for a language extension. See N1607 for details on the auto proposal.

However, the article on the Boost.Foreach (which sort of does what you want) macro may help understand the issues related to such an implementation.

What is BOOST_FOREACH?

In C++, writing a loop that iterates over a sequence is tedious. We can either use iterators, which requires a considerable amount of boiler-plate, or we can use the std::for_each() algorithm and move our loop body into a predicate, which requires no less boiler-plate and forces us to move our logic far from where it will be used. In contrast, some other languages, like Perl, provide a dedicated "foreach" construct that automates this process. BOOST_FOREACH is just such a construct for C++. It iterates over sequences for us, freeing us from having to deal directly with iterators or write predicates.

BOOST_FOREACH is designed for ease-of-use and efficiency. It does no dynamic allocations, makes no virtual function calls or calls through function pointers, and makes no calls that are not transparent to the compiler's optimizer. This results in near-optimal code generation; the performance of BOOST_FOREACH is usually within a few percent of the equivalent hand-coded loop. And although BOOST_FOREACH is a macro, it is a remarkably well-behaved one. It evaluates its arguments exactly once, leading to no nasty surprises.

like image 119
dirkgently Avatar answered Oct 24 '22 06:10

dirkgently


There's a BOOST_AUTO macro that more or less does what the auto keyword... However, one look at it's implementation will tell you that it's far better to find a way to use C++0x :>

like image 10
Kornel Kisielewicz Avatar answered Oct 24 '22 05:10

Kornel Kisielewicz


You can use these macros to work-around this in a Standard conforming manner.

#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; }

So your for-loop becomes

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

Credit goes to Conditional Love: FOREACH Redux, by Eric Niebler. Not sure whether this is really worth it though :)

like image 3
Johannes Schaub - litb Avatar answered Oct 24 '22 07:10

Johannes Schaub - litb