专门化成员指针模板参数解析

时间:2015-10-27 13:02:09

标签: c++ templates c++11

在C ++ 11上有一个守护类,它负责在作用域退出时调用某个成员函数:

template <class T, void (T::*op)()>
struct Guard
{
    Guard(T*g):
        _g(g){}
    ~Guard()
    {
        (_g->*op)();
    }
    T*_g;
};

用法非常简单:

typedef Guard<Foo, &Foo::bar> FooGuard;
...
FooGuard g(&foo);

我的问题来自现有的shared_ptr<Foo>。如何创建保留shared_ptr<T>而不是T*

的专业化

我已经尝试过:

template <class T, void (T::*op)()>
struct Guard<std::shared_ptr<T>, op>
{
    Guard(std::shared_ptr<T>& g):
        _g(g){}
    ~Guard()
    {
        ((*_g).*op)();
    }

    std::shared_ptr<T> _g;
};

但是在编译G<std::shared_ptr<Foo>, &Foo::bar> g2(foo);期间可以预见得到:

  

错误C2440:'specialization':无法从'overloaded-function'转换为'void(__thiscall std :: shared_ptr :: *)(void)'

3 个答案:

答案 0 :(得分:1)

我建议改用lambda函数并按值捕获:

#include <functional>
#include <memory>

struct Guard
{
    typedef std::function<void()> func_type;

    Guard( const func_type& f ): func(f) {}
    ~Guard() { if (func) func(); }

    func_type func;
};

struct Foo
{
    void bar() {}
};

int main()
{
    auto foo_ptr = std::make_shared<Foo>();
    Guard g([foo_ptr](){ foo_ptr->bar(); }); // note the capture by value
}

请注意,如果您想保护在堆栈上分配的实例,也可以通过引用自由捕获。

答案 1 :(得分:1)

正如@PiotrSkotnicki已经指出的那样,你的专业化无效。 您可以使用类似下面的内容,但界面看起来不太好:

template <class T, class U, void (U::*op)()>
struct Guard
{
    Guard(T*g):
        _g(g){}
    ~Guard()
    {
        std::cout << "normal guard" << std::endl;
        (_g->*op)();
    }
    T*_g;
};


template <class T, class U, void (U::*op)()>
struct Guard<std::shared_ptr<T>, U, op>
{
    Guard(std::shared_ptr<T>& g):
        _g(g){}
    ~Guard()
    {
        std::cout << "shared_ptr guard" << std::endl;
        ((*_g).*op)();
    }

    std::shared_ptr<T> _g;
};

<强>演示:

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

int main()
{
    Foo foo;
    {
        typedef Guard<Foo, Foo, &Foo::bar> FooGuard;
        FooGuard g(&foo);
    }

    std::shared_ptr<Foo> foo_ptr = std::make_shared<Foo>();
    {
        typedef Guard<std::shared_ptr<Foo>, Foo, &Foo::bar> FooGuard;
        FooGuard g(foo_ptr);
    }

    return 0;
}

<强>输出:

normal guard
Foo::bar()
shared_ptr guard
Foo::bar()

live example

答案 2 :(得分:1)

如果你真的想坚持丑陋的方式,我会建议使用删除器:

var date_res = $(this).find("td:nth-child(2)").find(".PL30").find("span").text();