c++ - Partial specialization of double-templated method fails -
there template class list.
template <typename point> class list { public: template <const unsigned short n> void load ( const char *file); ... }; template <typename point> template <const unsigned short n> void list <point>::load ( const char *file) }
how specialize method load n=2? code not valid...
template <typename point> void list <point> <2>::load ( const char *file) { }
and code not work.
template <typename point> void list <point> ::load <2> ( const char *file ) { } error 3 error c2768: 'list<point>::load' : illegal use of explicit template arguments 66. error 5 error c2244: 'list<point>::load' : unable match function definition existing declaration 66
compiler g++:
template <typename point> template <> void list <point> ::load <2> ( const char *file ) { } error: explicit specialization in non-namespace scope `class list<>' error: enclosing class templates not explicitly specialized error: default arguments permitted function parameters error: `load' not function template error: invalid function declaration
it turns out there's provision in c++ spec explicitly disallows specializing template class or function nested inside of template class unless explicitly specialize outer template well. visual studio doesn't enforce rule, hence confusion previous example, g++ does.
if want specialize template, options either specialize outer template or somehow fake behavior of specialization having method dispatch 1 of 2 different implementations based on template parameter. neither of these satisfying, know, unfortunately language designed weirdly in template corners. :-(
one way can emulate behavior of explicit specialization use technique called tag dispatching. idea we'll make simple struct looks this:
template <unsigned short n> struct box {};
this type empty. it's not meant used directly, rather way of embedding integer type system. in particular, box<3>
not same type box<4>
, etc.
next, in list class, define 2 functions this, preferably marked private:
template <unsigned short n> void doload(const char* file, box<n>); void doload(const char* file, box<2>);
these 2 functions overloads of 1 another, distinguishable final parameter, either box<n>
in template case or box<2>
in non-template case. note parameters don't have names. arbitrary decision, since we're not planning on reading parameters, don't need them. intuition behind these functions first function "catch-all" implementation work n
except 2. second version contain implementation of loading case n == 2
.
finally, implement load
follows:
template <typename point> template <unsigned short n> void list<point>::load(const char* file) { doload(file, box<n>()); }
how work? function takes in parameter, , calls doload
forwarding parameter first argument , passing temporary box<n>
second argument. if n
not two, call template version of doload
, catch-all handler. if, on other hand, n
two, call non-template version of doload
, because non-template functions have priority on template functions during overload resolution.
in short, implementation of load
becomes trampoline forward correct of 2 implementations. can put logic in appropriate doload
function behavior want.
hope helps!
Comments
Post a Comment