views:

147

answers:

4

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?

+9  A: 

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.

dirkgently
I think about implementation only for using in for like foreach. The C++0x's keyword auto have a lot of usages... Thanks for link, i'll read.
k06a
@k06a: There's a strong opposition in C++ to implement something as a new language feature when it can be implemented in a library. So if something ends up in the language proper you can be pretty sure that nobody has found a way to properly do it in a library. (For example, what `std::function` and `std::bind` do is built into the language in many other languages, but it's a library feature in C++.)
sbi
I've always wondered why BOOST_FOREACH is a few percent away from a "hand-coded" loop.
Viktor Sehr
Pavel Minaev
+8  A: 

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 :>

Kornel Kisielewicz
Thanks for link. Reading ...
k06a
Also, if the compiler doesn't support decltype or typeof, BOOST_AUTO will only be able to handle the built-in types as well as many standard library types. Other user.defined types have to be "registered" so that BOOST_AUTO recognizes them -- if I recall correctly.
sellibitze
+2  A: 

The more immediate problem is to get information from the deduced type to a data member declaration.

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

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

That's clearly not going to happen because the AUTO object must be allocated before the function is called.

Given typeof or decltype, it's not so hard, though.

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

Of course, this has a lot of restrictions. And typeof isn't standard. With multiple compiler support, this would probably be the basis for those Boost tools.

Potatoswatter
+2  A: 

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 :)

Johannes Schaub - litb