C++ C++;11简化调用同一模板函数的不同专门化的模板函数的语法
有两个模板函数(具有相同的签名),如:C++ C++;11简化调用同一模板函数的不同专门化的模板函数的语法,c++,c++11,templates,C++,C++11,Templates,有两个模板函数(具有相同的签名),如: 模板空位f1(T,P); 模板空隙f2(T,P); 还有两个具有相同逻辑的函数,它们使用不同的谓词调用它们: template <typename T> void g1(T t) { f1(t, Pred1{}); ... f1(t, Pred2{}); ... } // same as g1 but calls f2 instead of f1 template <typename T> voi
模板空位f1(T,P);
模板空隙f2(T,P);
还有两个具有相同逻辑的函数,它们使用不同的谓词调用它们:
template <typename T> void g1(T t)
{
f1(t, Pred1{});
...
f1(t, Pred2{});
...
}
// same as g1 but calls f2 instead of f1
template <typename T> void g2(T t)
{
f2(t, Pred3{});
...
f2(t, Pred4{});
...
}
模板无效g1(T)
{
f1(t,Pred1{});
...
f1(t,Pred2{});
...
}
//与g1相同,但调用f2而不是f1
模板无效g2(T)
{
f2(t,Pred3{});
...
f2(t,Pred4{});
...
}
我试图对它们进行概括,我能想到的是:
template <typename P1, typename P2, typename FP1, typename FP2, typename T>
void g(T t, FP1 fp1, FP2 fp2, P1 p1, P2 p2)
{
fp1(t, p1);
...
fp2(t, p2);
...
}
template <typename T> void g1(T t)
{
g(t, f1<T, P1>, f2<T, P2>, P1{}, P2{});
}
模板
无效g(T T,FP1 FP1,FP2 FP2,P1 P1,P2)
{
fp1(t,p1);
...
fp2(t,p2);
...
}
模板空隙g1(T)
{
g(t,f1,f2,P1{},P2{});
}
所以它过于冗长,特别是对于真实类型,而不是像本例中的玩具类型。
我必须分别传递在广义函数g()
中调用的每个f()
专门化,并且我必须两次提到每个谓词(第一,它在f专门化中的类型,第二,谓词对象作为单独的参数)
如果我从g()
中删除p1p1,p2p2
参数,我仍然必须像这样调用它:g(t,f1,f1)
有没有办法让它更简单,避免重复
我仅限于C++11/14。如果您可以将函数模板转换为functor模板(可调用结构),那么您将有一些自由来使用模板参数 例如:
template <template <typename...> typename Func, typename T, typename P, typename ...Ps>
struct Caller
{
void operator()(T t, P p, Ps ...ps)
{
Func<T, P>{}(t, p);
Caller<Func, T, Ps...>{}(t, ps...);
}
};
template <template <typename...> typename Func, typename T, typename P>
struct Caller<Func, T, P>
{
void operator()(T t, P p)
{
Func<T, P>{}(t, p);
}
};
template <template <typename...> typename Func, typename T, typename ...Ps>
void Call(T t, Ps ...ps)
{
Caller<Func, T, Ps...>{}(t, ps...);
}
template <typename T, typename P> struct f1 {
void operator()(T t, P p) { std::cout << "f1 " << t << ", " << p << "\n"; }
};
template <typename T, typename P> struct f2 {
void operator()(T t, P p) { std::cout << "f2 " << t << ", " << p << "\n"; }
};
int main() {
Call<f1>(1.0001, 2, 3.05f, 'x');
Call<f2>(2, 3, "bar!");
}
不幸的是,函数模板不能作为模板参数传递。如果您可以将函数模板转换为functor模板(可调用结构),那么您就可以自由使用模板参数 例如:
template <template <typename...> typename Func, typename T, typename P, typename ...Ps>
struct Caller
{
void operator()(T t, P p, Ps ...ps)
{
Func<T, P>{}(t, p);
Caller<Func, T, Ps...>{}(t, ps...);
}
};
template <template <typename...> typename Func, typename T, typename P>
struct Caller<Func, T, P>
{
void operator()(T t, P p)
{
Func<T, P>{}(t, p);
}
};
template <template <typename...> typename Func, typename T, typename ...Ps>
void Call(T t, Ps ...ps)
{
Caller<Func, T, Ps...>{}(t, ps...);
}
template <typename T, typename P> struct f1 {
void operator()(T t, P p) { std::cout << "f1 " << t << ", " << p << "\n"; }
};
template <typename T, typename P> struct f2 {
void operator()(T t, P p) { std::cout << "f2 " << t << ", " << p << "\n"; }
};
int main() {
Call<f1>(1.0001, 2, 3.05f, 'x');
Call<f2>(2, 3, "bar!");
}
很遗憾,函数模板不能作为模板参数传递。您不能有模板函数参数 传递重载的方法是将它们包装在Functor中 因此,您的通用
g
变成:
template <typename F, typename T>
void g(F f, T t)
{
f(t, Pred1{});
...
f(t, Pred2{});
...
}
在C++11中,functor更详细(尤其是在捕获时):
struct F1
{
模板
自动运算符()(T,Pred-Pred)常量{
返回f1(t,pred);
}
};
g(F1{},t);
您不能有模板函数参数
传递重载的方法是将它们包装在Functor中
因此,您的通用g
变成:
template <typename F, typename T>
void g(F f, T t)
{
f(t, Pred1{});
...
f(t, Pred2{});
...
}
在C++11中,functor更详细(尤其是在捕获时):
struct F1
{
模板
自动运算符()(T,Pred-Pred)常量{
返回f1(t,pred);
}
};
g(F1{},t);
谢谢,通用lambda正是我所需要的。我觉得自己很傻,因为我不知道如何应用它。谢谢,通用的lambda正是我所需要的。我为没有弄明白如何应用它而感到愚蠢。谢谢,这个解决方案甚至可以扩展到任意数量的谓词。不过我还是选择了更简单的通用lambda。谢谢,这个解决方案甚至可以扩展到任意数量的谓词。但我还是选择了更简单的通用lambda。
struct F1
{
template <typename T, typename Pred>
auto operator()(T t, Pred pred) const {
return f1(t, pred);
}
};
g(F1{}, t);