成员函数模板参数的部分特化?

时间:2016-12-20 14:14:41

标签: c++ c++11 variadic-templates variadic-functions

成员函数模板参数的部分特化是可能的吗?我不确定,但值得一试。 这很好(http://coliru.stacked-crooked.com/a/795e953af7537ab6):

> db.zoo.findOne()
{
    "_id" : ObjectId("5822bd23085f753b5a5a2408"),
    "name" : "Zoo 2",
    "active" : true,
    "archived" : false,
    "animals" : [
        DBRef("animals", ObjectId("556cc7adec045b1a0c8b4567"),{ "$db": "tester", "discriminator": "Test\\Bundle\\Core\\Document\\Animal" }),
        DBRef("animals", ObjectId("556cb3b0ec045bbf068b4582"),{ "$db": "tester", "discriminator": "Test\\Bundle\\Core\\Document\\Animal" })
    ]
}

输出:

#include <iostream>

struct Foo { void Bar() { std::cout << "Bar()" << std::endl; } };
struct Foo2 { void Bar2() { std::cout << "Bar2()" << std::endl; } };

template <typename TClass, void(TClass::*t_func)()>
void function()
{
    TClass p;
    (p.*t_func)();
}

template <typename TClass, void(TClass::*t_func)(), typename TClass2, void(TClass2::*t_func2)(), typename ...Rest>
void function()
{
    function<TClass, t_func>();
    function<TClass2, t_func2, Rest...>();
}

int main()
{
    function<Foo, &Foo::Bar, Foo2, &Foo2::Bar2>();
}

下一个示例也适用(http://coliru.stacked-crooked.com/a/e8fe14dde6932f4c):

Bar()
Bar2()

输出:

#include <iostream>

struct Foo { Foo() { std::cout << "Foo()" << std::endl; } };
struct Foo2 { Foo2() { std::cout << "Foo2()" << std::endl; } };

template <typename... Args>
struct Impl;

template <typename TClass, typename ...Rest>
struct Impl<TClass, Rest...>
{
    static void function()
    {
        TClass p;
        Impl<Rest...>::function();
    }
};

template <>
struct Impl<>
{
    static void function(){ std::cout << "EmptyImpl" << std::endl; }
};

template <typename ...Args>
struct Factory
{
    Factory()
    {
        Impl<Args...>::function();
    }
};

int main()
{
    auto f = Factory<Foo, Foo2>();
}

但如果我想将上述两点结合起来:

Foo()
Foo2()
EmptyImpl

这将是编译器错误:

#include <iostream>

struct Foo { void Bar() { std::cout << "Bar()" << std::endl; } };
struct Foo2 { void Bar2() { std::cout << "Bar2()" << std::endl; } };

template <typename... Args>
struct Impl;

template <typename TClass, void(TClass::*t_func)(), typename ...Rest>
struct Impl<TClass, decltype(t_func), Rest...>
{
    static void function()
    {
        TClass p;
        Impl<Rest...>::function();
    }
};

template <>
struct Impl<>
{
    static void function(){}
};

template <typename ...Args>
struct Factory
{
    Factory()
    {
        Impl<Args...>::function();
    }
};

int main()
{
    auto f = Factory<Foo, &Foo::Bar, Foo2, &Foo2::Bar2>();
}

有什么想法吗?我错过了什么? :)

1 个答案:

答案 0 :(得分:0)

考虑使用额外的包装器来调用成员函数

#include <iostream>

struct Foo { void Bar() { std::cout << "Bar()" << std::endl; } };
struct Foo2 { void Bar2() { std::cout << "Bar2()" << std::endl; } };

template <class TClass>
using FType = void(TClass::*)();

template<class TClass, FType<TClass> t_func>
class Caller
{
public:
  Caller()
  {
    TClass p;
    (p.*t_func)();
  }
};

template <typename... Args>
struct Impl;

template <class TClass, typename ...Rest>
struct Impl<TClass, Rest...>
{
    static void function()
    {
        TClass p;
        Impl<Rest...>::function();
    }
};


template <>
struct Impl<>
{
    static void function(){}
};

template <class ...Args>
struct Factory
{
    Factory()
    {
        Impl<Args...>::function();
    }
};

int main()
{
    auto f = Factory<Caller<Foo, &Foo::Bar>, Caller<Foo2, &Foo2::Bar2> >();
}