Template function as a template argument

佐手、 提交于 2019-11-27 11:34:58

In order to solve this problem with templates, you have to use a template template parameter. Unfortunately, you cannot pass template template function as a type, because it has to be instantiated first. But there is a workaround with dummy structures. Here is an example:

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

Here's a way. It may not be the best, but it works:

template <typename T, T param>
void function() {
    param(123);
    param(456);
}

void test()
{
    function< void(*)(int), a<int> >(); // space at end necessary to compiler
    function< void(*)(int), b<int> >(); // because the C++ grammar is ambiguous
}

Whether or not they'll be inlined depends on the compiler, but I would be rather surprised if they weren't.

EDIT: Okay, I'm a little off today and missed the part where the parameters are of different types. My bad.

There may be a tricky way to do this with templates, but this is the easiest way I could think of:

#define function(x) do { x<thing1>(obj1); x<thing2>(obj2) } while(0)

I know, I know, "macros are evil," blah blah blah. It works. If function needs to be more complicated than your example you may run into problems, but it is much easier than anything I've been able to come up with.

With lambda from C++11, you might do:

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

Can compilers still inline the calls if they are made via function pointers?

They can, but it is indeed more complicated, and they may fail more often than with functor or template.

template < typename F >
void function(F f)
{
  f(123);
}

void a(int x) { ... }

struct b { void operator() (int x) { ... } };

void outer()
{
  function(&a);
  function(b());
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!