c++ - choosing appropriate specialized template at runtime -
i using class 3rd party library like,
template <typename = defaultt, typename b = defaultt, typename c = defaultt, typename d = defaultt, typename e = defaultt, typename f = defaultt> class vertex {};
i want use partial specialization of class @ runtime depending on conditions, example,
class mya {}; class myb {}; class myc {}; class myd {}; bool usea, useb, usec, used; //these booleans change @ runtime // want specialize vertex depending on above booleans // below line shouldn't compile, give idea typedef typename vertex <usea ? mya : defaultt, useb ? myb : defaultt, usec ? myc : defaultt, used ? myd : defaultt> myvertex;
i want conditionally choose template arguments want specialize. not sure if there's term problem, doubt it's flavor of multiple dispatch.
a simple way write 15 (2^4 -1) classes like,
typedef typename vertex <mya> myvertexwitha; typedef typename vertex <defaultt, myb> myvertexwithb; typedef typename vertex <mya, myb> myvertexwithab; //and on...until typedef typename vertex <mya, myb, myc, myd> myvertexwithabcd;
the problem becomes more complicated because have use 'mesh' class uses specialized vertex class
template <typename vertexclass, typename others> class mesh {};
now if went down path of writing 15 classes have write 15 more lines each different mesh type. , keeps getting more complicated mesh class used.
i believe has done either me or compiler. questions:
- i want know if there's way make compiler work me?
- does c++11 have better mechanism handle scenario? thanks.
the answer no. if conditions change @ runtime, cannot specialize/instantiate templates based on conditions, need constant expressions (after all, compiler performs work @ compiler time, before program starts running, using run-time expressions no-no). if determined @ compile time, can use constexpr
tricks in combination std::conditional
.
as @karloy horvath mentioned, can called tag dispatching, similar example below:
#include <iostream> struct tag_yes{}; struct tag_no{}; template <typename t> void f_tag(); template <> void f_tag<tag_yes>() // specializations { std::cout << "yes" << std::endl; } template <> void f_tag<tag_no>() { std::cout << "no" << std::endl; } void f(bool condition) { if(condition) f_tag<tag_yes>(); // call yes specialization else f_tag<tag_no>(); // call no specialization } int main() { bool condition = true; f(condition); // dispatch "right" template function }
or, can deduce tag (that's how standard c++ algorithms work various iterator types)
#include <iostream> #include <type_traits> struct foo { using tag = std::true_type; }; struct bar { using tag = std::false_type; }; template <typename t> void f_tag(); template <> void f_tag<std::true_type>() // specializations { std::cout << "yes" << std::endl; } template <> void f_tag<std::false_type>() { std::cout << "no" << std::endl; } template <typename t> void f(const t&) { f_tag<typename t::tag>(); // dispatch call } int main() { foo foo; bar bar; f(foo); // dispatch f_tag<std::false_type> f(bar); // dispatch f_tag<std::true_type> }
however, in case polymorphism way go, via factory method , common virtual interface.
Comments
Post a Comment