Topic: template argument deduction for class templates
Author: spam@spamguard.com ("Gene Bushuyev")
Date: Sun, 20 Nov 2005 15:49:12 GMT Raw View
Function templates already enjoy the argument deduction as described in 14.8.2
chapter of the Standard. The question is: why not class templates? Why can't
class constructors follow exactly the same rules of template argument deduction?
Let me illustrate it with example. An std::pair class:
template <class T1, class T2>
struct pair {
// other members
pair(const T1& x, const T2& y);
};
This code could benefit from argument deduction:
std::pair(1,2); // same as std::pair<int,int>(1,2);
compiler could try deducing template parameters for all constructors and resolve
overloads the same way as it does for function templates. As a result there
would be no need for a common kludge, using a nonmember function just to deduce
template parameters, e.g. std::make_pair(1,2).
It can be used to declare and define variables as well:
std::pair p(1,2); // same as std::pair<int, int> p(1,2);
Those of course, are all toy examples. The real advantage comes in template
metaprogramming and situations where the proposed "auto" keyword is intended. In
metaprogramming, the functions often return some template
Type<complicated_arguments>. It's usually not the Type but the
complicated_arguments that present the problem of declaring a variable of that
type. A simplified parser example:
class Rule;
template<class R1, class R2>
class And;
template<class R1, class R2>
And<R1,R2> operator & (R1, R2);
One would be able to write:
Rule r1,r2,r3,r4;
And r = r1 & r2 & r3 & r4;
Compiler can deduce the template argument types and compile it as if was
written:
And<Rule, And<Rule, And<Rule, Rule> > > r = r1 & r2 & r3 & r4;
One could be able to make a copy of any type:
template<class T>
struct Copy
{
T t;
Copy(const T& t) : t(t) {}
};
Copy c(r1 & r2 & r3 | r4 & r5);
which is equivalent to Copy<Or<And<Rule, And<Rule,Rule> >, And<Rule,Rule> > >.
If argument deduction goes beyond constructors to typedefs, nested classes, etc.
there are all sorts of useful tricks it can be used for. One could be able to
provide a typeof(expression) alternative:
template<class T>
struct typeof
{
typedef T type;
};
typename typeof::type t(expression);
Compiler can deduce the type of T as that of "expression," so it will be
equivalent to:
typeof<expression_type>::type t(expression);
An iterator example:
for(typename std::vector::iterator i = v.begin();
i != v.end(); ++i)
{
typename std::vector::iterator i1 = ...;
// ...
std::distance(i, i1); // this is efficient
}
On the other hand, with "auto":
for(auto i = v.begin(); i != v.end(); ++i)
{
auto i1 = ...;
// ...
std::distance(i, i1);
// is this efficient?
}
"auto" would completely obliterate the visible type information, which can
become a source of errors.
Unlike "auto" proposal, extending argument deduction to class templates doesn't
have problems with overloading keyword meaning, doesn't completely hide the type
information, doesn't impact existing code, and doesn't require from compilers
more than what they already capable of doing.
-- Gene Bushuyev
----------------------------------------------------------------
There is no greatness where there is no simplicity, goodness and truth. ~ Leo
Tolstoy
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]