C++复杂类型的单一方法的模板专用化

C++ template specialization for a single method for complex types

本文关键字:专用 单一 复杂 类型 C++ 方法      更新时间:2023-10-16

我有一个抽象类和子类,如下所示:

class MyAbstractClass {
public:
    virtual bool shouldDoIt() = 0;
}
template <class T> class MyClass : public MyAbstractClass {
public:
    bool shouldDoIt() { return state; }
private: // assume there are appropriate accessors for these private fields
    bool state;
    T val;
}

这种shouldDoIt()实现适用于大多数类型。但是如果T恰好是一个std::vector<std::shared_ptr<MyClass<X>>>,其中X可以是任何类型的,那么我希望实现是这样的:

bool shouldDoIt() {
    if(state) return true;
    for(auto &member : val) {
        if(member->state) return true;
    }
    return false;
}

如果它是一个std::unordered_map<X, std::shared_ptr<MyClass<Y>>,其中XY可以是任何类型的,我想要这个实现:

bool shouldDoIt() {
    if(state) return true;
    for(auto &member : val) {
        if(member.second->state) return true;
    }
    return false;
}

我怎样才能专门为这些类型实现 shouldDoIt((?我正在使用Visual Studio 2015。

有几个选项可以执行此操作,我会选择哪一个取决于我希望这种特殊行为可自定义的程度。根据您在此处显示的内容,我可能会使用重载函数:

template <class T>
class MyClass : public MyAbstractClass {
public:
    bool shouldDoIt() {
        if (state) return true;
        return specializedShouldDoIt(val);
    }
private:
    template <class U>
    static bool specializedShouldDoIt(U&) { return false; }
    template <class X>
    static bool specializedShouldDoIt(
                        std::vector<std::shared_ptr<MyClass<X>>> &val) {
        // your loop is equivalent to std::any_of
        return std::any_of(val.begin(), val.end(), [](auto &member) {
            return member->state;
        });
    }
    template <class X, class Y>
    static bool specializedShouldDoIt(
                   std::unordered_map<X, std::shared_ptr<MyClass<Y>>> &val) {
        return std::any_of(val.begin(), val.end(), [](auto &member) {
            return member.second->state;
        });
    }
};

可能考虑的另一种选择是使用外部帮助程序类,以便我可以使用部分专用化:

template <class T>
struct PerformShouldDoIt
{
    static bool shouldDoIt(bool state, T&) { return state; }
};
template <class X>
struct PerformShouldDoIt<std::vector<std::shared_ptr<MyClass<X>>>>
{
    static bool shouldDoIt(bool state,
                           std::vector<std::shared_ptr<MyClass<X>>>& val) {
        return std::any_of(val.begin(), val.end(), [](auto &member) {
            return member->state;
        });
    }
};
// Similarly for whatever you wanted to specialize for
...
template <class T>
class MyClass : public MyAbstractClass {
public:
    bool shouldDoIt() {
        return PerformShouldDoIt<T>::shouldDoIt(state, val);
    }
};