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);