模板函数作为模板参数

Kos*_*Kos 31 c++ templates dry generic-programming

我很困惑如何在C++中以通用方式实现某些东西.这有点令人费解,所以让我一步一步解释.


考虑这样的代码:

void a(int) {
    // do something
}
void b(int) {
    // something else
}


void function1() {
    a(123);
    a(456);
}
void function2() {
    b(123);
    b(456);
}

void test() {
    function1();
    function2();
}
Run Code Online (Sandbox Code Playgroud)

很容易注意到function1并function2做同样的事情,唯一不同的部分是内部功能.

因此,我想制作function通用的以避免代码冗余.我可以使用函数指针或模板来完成它.我现在就选择后者.我的想法是,它更好,因为编译器肯定能够内联函数 - 我是否正确?编译器是否可以通过函数指针进行内联调用?这是一个侧面问题.

好的,回到原点...带模板的解决方案:

void a(int) {
    // do something
}
void b(int) {
    // something else
}

template<void (*param)(int) >
void function() {
    param(123);
    param(456);
}

void test() {
    function<a>();
    function<b>();
}
Run Code Online (Sandbox Code Playgroud)

一切都好.但是我遇到了一个问题:我还可以做,如果a和b是仿制药自己?

template<typename T>
void a(T t) {
   // do something
}

template<typename T>
void b(T t) {
   // something else
}

template< ...param... > // ???
void function() {
    param<SomeType>(someobj);
    param<AnotherType>(someotherobj);
}

void test() {
    function<a>();
    function<b>();
}
Run Code Online (Sandbox Code Playgroud)

我知道模板参数可以是以下之一:

  • 一种,
  • 模板类型,
  • 一个类型的值.

这似乎都没有涵盖我的情况.我的主要问题是:我如何解决这个问题,即function()在最后一个例子中定义 ?

(是的,在这个确切的情况下,函数指针似乎是一种解决方法 - 只要它们也可以内联 - 但我正在寻找这类问题的通用解决方案).

小智 29

要使用模板解决此问题,您必须使用模板模板参数.不幸的是,您无法将模板模板函数作为类型传递,因为它必须首先实例化.但是有一个虚拟结构的解决方法.这是一个例子:

template <typename T>
struct a {

    static void foo (T = T ())
    {
    }

};

template <typename T>
struct b {

    static void foo (T = T ())
    {
    }

};

struct SomeObj {};
struct SomeOtherObj {};

template <template <typename P> class T>
void function ()
{
    T<SomeObj>::foo ();
    T<SomeOtherObj>::foo ();
}

int main ()
{
    function<a>();
    function<b>();
}
Run Code Online (Sandbox Code Playgroud)

  • 总结一下:唯一可以内联调用的解决方案是用函子替换函数?有点笨拙,但我认为完全可以接受。谢谢! (2认同)

Jar*_*d42 8

使用 C++14 中的泛型 lambda,您可以这样做:

template<typename T> void a(T t) { /* do something */}
template<typename T> void b(T t) { /* something else */ }

template <typename F>
void function(F&& f) {
    f(someobj);
    f(someotherobj);
}

void test() {
    // For simple cases, auto&& is even probably auto or const auto&
    function([](auto&& t){ a(t); });
    function([](auto&& t){ b(t); });

    // For perfect forwarding
    function([](auto&& t){ a(std::forward<decltype(t)>(t)); });
    function([](auto&& t){ b(std::forward<decltype(t)>(t)); });
}
Run Code Online (Sandbox Code Playgroud)

如果通过函数指针进行调用,编译器仍然可以内联调用吗?

它们可以,但它确实更复杂,并且它们可能比函子或模板更容易失败。