Reputation: 155
Currently I implemented two template functions, each returning a template function pointer wrapped using boost::variant:
Function fa
typedef boost::variant<&A<int>,&A<double>> A_T;
A_T fa(string type)
{
switch(type){
case "int": return &A<int>;
case "double": return &A<double>;
default: return &A<int>;
}
}
Function fb
typedef boost::variant<&B<int>,&B<double>> B_T;
B_T fb(string type)
{
switch(type){
case "int": return &B<int>;
case "double": return &B<double>;
default: return &B<int>;
}
}
My question is "Can we merge the two functions into one template function which takes the functor pointer of A or B as template parameter?". The reason why I need this is because I may have more than two functors like A and B.
Upvotes: 2
Views: 887
Reputation: 29193
Simple:
template<template<typename> class F> // template template
using F_T = boost::variant<F<int>&, F<double>&>; // Need C++11 for this (not strictly needed) alias
template<template<typename> class F>
F_T<F> f(std::string type) {
if(type == "double") return something<F<double>&>();
else return something<F<int>&>();
}
using A_T = F_T<A>;
A_T at = f<A>("int");
// F_T<int> broken; // invalid: int is not a template<typename> class
// f<int>("int") // invalid: int is not a template<typename> class
A
is template<typename> class
, so it may be the type argument to F_T
and f
, which are both template<template<typename> class>
. Compare having a function a => b
and passing it as argument to a function (a => b) => c
. We say that a function [](int i) { return i + 5; }
has type int => int
, just like a type template<typename> class A
has kind * -> *
(concrete type to concrete type). Just like higher-order functions can have types like (A => A) => A
, higher-kinded types can have kinds like (* -> *) -> *
, e.g. F_T
. Normal types like int
and A_T<A>
which can be used as type of variables have kind *
.
Theory aside, it's rather intuitive that you can have template template parameters like this, even if the syntax looks wonky at first.
Upvotes: 1