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)
{
...
}
开发者_StackOverflow社区
But, T1 and T2 are different. How to move info about T1 to operator T2()? Is it really possible?
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.
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 :>
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 :)
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.
精彩评论