c++ 使用访问者模式而不写入过多重载

2cmtqfgy  于 2022-11-19  发布在  其他
关注(0)|答案(2)|浏览(109)

我有两种数据类型,分别称为DragonVectorUnbiasedDragon,我使用访问者模式进行动态类型推断。
我想把DragonVector只扩展一个DragonVector,类似地扩展UnbiasedDragon
下面的代码可以用来扩展向量:

template<class T>
class ExtendVisitor{
    public:
    void operator()(DragonVector<T>& vec1, const DragonVector<T>& vec2){
        vec1.extend(vec2);
    }
    void operator()(UnbiasedDragon<T>& vec1, const UnbiasedDragon<T>& vec2){
        vec1.extend(vec2);
    }
    void operator()(auto& vec1, const auto& vec2){
        std::cout<<"wrong class"<<std::endl;
    } 
};

我得到了error: 'auto' not allowed in function prototype。我使用的是C++17。
由于只有两个类,我可以在访问器中为所有组合编写操作符重载,但这似乎不可行,因为类的数量越来越大。
我试着使用模板作为一种变通方法,

template<class T>
class ExtendVisitor{
    public:
    void operator()(DragonVector<T>& vec1, const DragonVector<T>& vec2){
        vec1.extend(vec2);
    }
    void operator()(UnbiasedDragon<T>& vec1, const UnbiasedDragon<T>& vec2){
        vec1.extend(vec2);
    }
    template<class TT>
    void operator()(TT& vec1, const TT& vec2){
        std::cout<<"wrong class"<<std::endl;
    } 
};

但这也没有成功。
有没有一种方法可以使用访问者模式而不必编写所有可能的组合?

qxgroojn

qxgroojn1#

您 可以 将 它 作为 模板 来 捕获 所有 其他 组合 。 在 您 的 尝试 中 , 您 的 方法 具有 相同 类型 的 两 个 参数 , 但 您 需要 不同 的 类型 :

template <typename A,typename B>
void operator()(A& vec1, const B& vec2){
    std::cout<<"wrong class"<<std::endl;
}

中 的 每 一 个
也 可以 使用 lambdas , 如下 例 所 示 :https://en.cppreference.com/w/cpp/utility/variant/visit 。 泛型 lambda 从 C + +14 开始 就 可用 了 。

6pp0gazn

6pp0gazn2#

第一个代码片段中的语法从C++20开始就可用,它可以按预期工作。
第二个代码段不起作用,只是因为在默认重载中强制两个参数的大小写相同。应该有两个模板参数,每个函数参数一个。
但是,无论如何都没有必要使它变得如此复杂。您可以使用一个模板,然后在其主体中实现您的条件(类型相等):

template<typename T, typename U>
void operator()(T& t, const U& u){
    static_assert(!std::is_const_v<T>, "ExtendVisitor requires the left-hand to be modifiable!");

    if constexpr(std::is_same_v<T, U>) {
        vec1.extend(vec2);
    } else {
        // You should probably throw an exception here instead!
        std::cout<<"wrong class"<<std::endl;
    }
}

相关问题