Re: matching multiple template
On Jul 10, 7:25 am, "Eric Pruneau" <eric.prun...@cgocable.ca> wrote:
[...]
------------------------
Eric Pruneau
Thanks for answering.
Actually this is what i have already. What i want is to match both
const & non const version in same specialization something like (this
is not a valid syntax of course),
template<typename T>
struct Indexer<T,const vector<T> | vector<T> >
{
Indexer() { cout <<"3\n"; }
};
so i want both the match to succeed in same specialization. Also i
need to know which match is there.
i don't know if it is directly possible, but i am thinking having a0
proxy class to delegate the responsibility.
thanks
abir
Ok you leave me no choice but to use the big guns!!!
here is a solution using boost type triats and enable_if
template<typename T, typename CONT, typename enable=void>
struct Indexer
{
Indexer() { cout <<"1\n"; }
};
// this one could be a bit scary....
template<typename T, typename CONT>
struct Indexer<T, CONT, typename boost::enable_if_c<boost::is_same<
typename boost::add_const<CONT>::type , const vector<T> >::value>::type
>
{
Indexer() { cout <<"2\n"; }
};
int main()
{
Indexer<int, vector<int> > a; // print 2
Indexer<int, const vector<int> > b; // guess what? it prints 2 !!!
Indexer<int, deque<int> > c; // print 1
return 0;
}
ok here is the trick
add_const<CONT>::type just add a const before CONT if CONT is not already
const. it does nothing if CONT is already const.
then we do:
is_same<const CONT, const vector<T> >::value
this returns true if const CONT = const vector<T>
finally enable_if_c has 2 template parameter (the second is void by default)
The first one must be a bool
enable_if_c<true>::type return void
enable_if_c<false>::type is an error
so if
is_same<const CONT, const vector<T> >::value
returns true we got a match and the second template Indexer is used.
if const CONT is not a const vector then the first template Indexer is used.
you can find the boost library here www.boost.org
It is a must . If you don't have it, get it!
-------------------------
Eric Pruneau
oh concern to my last post about how to get rid of the extra int ,
i was stupid enough to forget that CONT::value_type is T,
so my final version is
template<typename S,typename enable = void>
class Indexer;
template<typename S>
class Indexer<S,typename boost::enable_if_c<std::tr1::is_same<
typename std::tr1::add_const<S>::type, const
std::vector<typename S::value_type,typename
S::allocator_type>>::value>::type
> {
public:
typedef Indexer<S> self_type;
typedef Indexer<typename std::tr1::remove_const<S>::type>
nonconst_self;
public:
Indexer(S& s) {
std::cout<<"vec ctor\n";
}
Indexer(nonconst_self& s){
std::cout<<"vec copy\n";
}
};
template<typename S>
class Indexer<S,typename boost::enable_if_c<std::tr1::is_same<
typename boost::add_const<S>::type, const
std::deque<typename S::value_type,typename
S::allocator_type>>::value>::type
> {
public:
typedef Indexer<S> self_type;
typedef Indexer<typename std::tr1::remove_const<S>::type>
nonconst_self;
public:
Indexer(S& s) {
std::cout<<"deq ctor\n";
}
Indexer(nonconst_self& s){
std::cout<<"deq copy\n";
}
};
and calling syntax is
typedef std::vector<int> VI;
VI v;
Indexer<VI> I1(v);
Indexer<const VI> I2(v);
Indexer<const VI> I3(cv);
//Indexer<int,std::allocator<int>,VI> I4(cv);
Indexer<QI> I10(q);
this is what i wanted, and hence the problem is solved.
Thanks a lot to all.
abir