如何在C ++ 11模板中定义时调用它

时间:2014-10-10 14:41:30

标签: c++ c++11

查看这样一个简单的模板场景:

class A {
    public:
        int work();
};

class B {
    public:
        int work();
};

class ObjectManager {
    public:
        static void manage( A& obj );
        // manage not defined for class B 
};

template<class T>
doStuff( T t ) {
    t.work();
    ....
    ObjectManager::manage(t);
};


A a;
B b;

doStuf(a);
doStuff(b);

我想知道,对ObjectManager::manage实施条件调用的最简洁方法是什么?模板函数应该在编译时确定是否为给定的ObjectManager::manage(T t)定义了T,并且仅在它被激活时激活某些代码行。我猜有一些嵌套模板调用的解决方案,但对我来说最好只是将函数保持为一个整体。

1 个答案:

答案 0 :(得分:5)

请注意,目前您的班级成员都是私人的。它们应该公开。

template<class T>
auto call_manage(T* t) -> decltype(ObjectManager::manage(*t)){
    return ObjectManager::manage(*t);
}

void call_manage(...) {}

template<class T>
void doStuff( T t ) {
    t.work();
    //....
    call_manage(std::addressof(t)); // smack whoever overloaded unary 
                                    // operator & in the head first
}

如果表达式ObjectManager::manage(*t)格式正确,则函数模板的替换成功,它总是比...更好的匹配,因此它被调用。否则,do-nothing过载是唯一可行的功能。

Demo


对于喜欢参考的人:

template<class T>
auto call_manage(T& t) -> decltype(ObjectManager::manage(t)){
    return ObjectManager::manage(t);
}

template<class... T>
void call_manage(T&&...) {}

template<class T>
void doStuff( T t ) {
    t.work();
    //....
    call_manage(t);
}

在这种情况下,单参数重载比功能模板的部分排序规则的可变参数版本更专业,并且如果两者同样可行,则通过重载决策选择。您也可以点T&& t并致电manage(std::forward<T>(t)),以便完美转发。

Demo