c++ - Why is template specialization of variadic templates different from specialization of non-variadic templates? -
i'm don't understand why template specialization different variadic templates regular (i.e., non-variadic) templates. example have template , specialization like:
enum class mf : int { 0 = 0, 1 = 1, 2 = 2 }; // --------- specialization ------------- template <mf mf> class stat{ public: stat(std::string msg) { cout << "generic stat construtor: " << msg << endl; } }; // --------- template specialization ------------- template<> class stat<mf::one>{ public: stat(std::string msg) { cout << "specialized stat constructor: " << msg << endl; } };
i have specialized specific value of mf
enumeration.
now if want specialize variadic template can't specialize variadic template parameters specific value of mf
enumeration (e.g., mf::one
), can specialize type, (e.g. mf
).
// --------- variadic template ------------- template<mf mf, typename... e> class var{ public: var(std::string msg){ cout << "generic var constructor: " << msg << endl; } }; // --------- variadic template specialization ------------- template<> class var<mf::two, mf>{ public: var(std::string msg){ cout << "specialized var constructor: " << msg << endl; } };
i specialize variadic template specific mf
value, doesn't appear can.
is there aspect of language i'm missing allow me want? along lines of:
template<> class var<mf::two, mf::one>{ public: var(std::string msg){ cout << "specialized var constructor: " << msg << endl; } };
complete example can found here
template
s not macros. typename...
not mean "take number of comma delimited strings". typename...
means "take 0 or more types".
mf::one
not type.
attempting pass mf::one
template
expects typename...
error, because template
asking typename
not value.
you can write template class
takes 0 or more mf
s. can write 1 takes 0 or more types. cannot write template class
takes 0 or more mf
s or types. c++ not support that.
if must pass values via type, there std::integral_constant< type, value >
, type wraps integral constant value.
template<mf mf, typename... e> class var; template<> class var<mf::two, std::integral_constant<mf, mf::one>>{ public: var(std::string msg){ cout << "specialized var constructor: " << msg << endl; } };
you'd instantiate var<mf::two, std::integral_constant<mf, mf::one>>
.
you can create aliases:
template<mf mf> using mf_t=std::integral_constant<mf, mf>;
to make code nicer:
template<mf mf, typename... e> class var; template<> class var<mf::two, mf_t<mf::one>>{ public: var(std::string msg){ cout << "specialized var constructor: " << msg << endl; } }; int main() { var<mf::two, mf_t<mf::one>> instance("hello");; }
for metaprogramming purposes, wise idea write templates taking types, , never taking constants, , when need constant stuff type above. template<class...>class x
match such template.
you can gain access value of std::integral_constant
::value
or constructing , converting value of type. (in c++1y , many c++11 compilers, conversion constexpr
).
so
mf x = mf_t<mf::one>{}; mf y = mf_t<mf::one>::value;
will set x
, y
mf::one
. in both cases, right hand side should compile time expression, so:
mf_t< mf_t<mf::one>{} >
is valid type (if silly written one) same mf_t< mf::one >
.
Comments
Post a Comment