C++ 将静态访问者与静态多态层次结构耦合

C++ 将静态访问者与静态多态层次结构耦合,c++,crtp,template-function,static-polymorphism,static-visitor,C++,Crtp,Template Function,Static Polymorphism,Static Visitor,我的程序的目的是创建一个数据列表,在类层次结构中使用静态多态性时,我可以使用一组静态访问者访问这些数据 我通过CRTP创建了一个利用静态多态性的类层次结构: class VirtualBaseData { public: //someVirtualFunction } template<typename Derived> class BaseData<Derived> { public: template<typename Visitor&

我的程序的目的是创建一个数据列表,在类层次结构中使用静态多态性时,我可以使用一组静态访问者访问这些数据

我通过CRTP创建了一个利用静态多态性的类层次结构:

class VirtualBaseData {
public:    
    //someVirtualFunction
}

template<typename Derived>
class BaseData<Derived> {
public:
    template<typename Visitor>
    void accept(Visitor &v){
         static_cast<Derived*>(this)->accept(v);
    }
}

class DerivedBaseData1: BaseData<DerivedBaseData> {
public:
    template<typename Visitor>
    void accept(Visitor &v){
         //Specific implementation
    }    
}
class DerivedBaseData2: BaseData<DerivedBaseData> {
public:
    template<typename Visitor>
    void accept(Visitor &v){
         //Specific implementation
    }    
}
class虚拟数据库数据{
公众:
//某种虚拟功能
}
模板
类基础数据{
公众:
模板
无效接受(访客和验证){
静态(本)->接受(v);
}
}
类DerivedBaseData1:BaseData{
公众:
模板
无效接受(访客和验证){
//具体实施
}    
}
类DerivedBaseData2:BaseData{
公众:
模板
无效接受(访客和验证){
//具体实施
}    
}
我想将DerivedBaseData存储在一个容器中,以便稍后进行迭代和访问

int main(){
    std::vector<VirtualBaseData*> dataSet;
    dataSet.push_back(new DerivedBaseData1);
    dataSet.push_back(new DerivedBaseData2);
    for(auto it = fifth.begin(); it != fifth.end(); ++it){
        it->accept(); //Error: VirtualBaseData does not have a member function accept
    }
}
intmain(){
向量数据集;
dataSet.push_back(新的DerivedBaseData1);
dataSet.push_back(新的DerivedBaseData2);
for(auto it=fifth.begin();it!=fifth.end();+it){
it->accept();//错误:VirtualBaseData没有成员函数accept
}
}
我正在寻找一种将静态访问者与静态多态层次结构结合起来的方法。 我的静态多态性中需要一个VirtualBaseData类,它不是一个模板类,以便在容器中使用这些类。 但是,由于我不能将VirtualBaseData类作为模板类,因此我无法像在CRTPattern中那样为派生类创建适当的静态转换

我的问题是:有没有人有一个好的策略可以保留我的静态多态性设置以及静态访问者模式


仅供参考:我已经实现了第21-23页中所述的静态访问者,错误是正确的,因为您正在创建VirtualBaseData指针的向量。类VirtualBaseData不包含accept()函数

你的答案是:

还可以阅读多态性:

正如您所说,没有简单的解决方案,但您可能希望使用运行时多态性而不是静态多态性。为了归档运行时多态性,您需要对基类执行类型擦除,并分派到适当的非temapte函数。例如,可以使用boost库中的
boost::any
对其进行存档。
boost::any
的约束是存储为
boost::any
的所有对象都必须是可复制的。如果
boost::any
不适合您,请阅读有关类型擦除的更多信息

class VirtualBaseData {
public:    
    template <typename T>
    void accept(T& visitor) {
        acceptImpl(boost::any(visitor));
    }
protected:
    virtual void acceptImpl(boost::any const & value ) = 0;
}
class虚拟数据库数据{
公众:
模板
无效接受(T和访客){
acceptImpl(boost::any(visitor));
}
受保护的:
虚拟void acceptImpl(boost::any const&value)=0;
}

如果您不知道在编译时您的对象将有多少/什么类型,那么这就是动态多态性的一个用例(至少,我不知道如何仅使用静态多态性)

然而。。。如果您在编译时知道对象的确切数量和类型,那么现在我们开始讨论!下面是一个最小的编译示例():

#包括
#包括
#包括
使用名称空间std;
模板
类基础数据{
公众:
模板
无效接受(访客和验证){
静态(本)->接受(v);
}
};
类DerivedBaseData1:BaseData{
公众:
模板
无效接受(访客和验证){

std::非常感谢您的快速回复。但是我可以看出我的问题被误解了,所以我将在这里和原始问题中重新措辞。我正在寻找一种方法,将我的静态访问者与我的静态多态层次结构结合起来。我需要在我的静态多态性中使用VirtualBaseData类,它不是模板类为了在容器中使用类。但是,由于我不能将VirtualBaseData类作为模板类,因此我无法像在CRTPattern中那样为派生类创建适当的静态转换。“将‘accept’设置为虚拟函数是不合适的,因为它需要指定的访问者来保留程序的静态访问者部分。“这在没有上下文的情况下毫无意义。你能通过演示一个特定的问题或错误来说明你的意思吗?一般来说,一旦你将指向派生对象的指针推到一个基本指针容器中,你就已经擦除了类型,而让它们返回的唯一方法就是调用一个虚拟函数。”(由于可伸缩性问题,动态强制转换不起作用)。我将问题重新表述为clearify。我有一组静态访问者,我希望将其传递给“accept”函数,以便访问者在对象中执行一些计算。这可以通过模板化类和调用派生类的“accept”函数来实现。不过,我还希望迭代一组数据对象。为了在保持静态多态层次结构的同时做到这一点,我实现了vbd(virtualbasedata)类。因此,我无法使vbd类成为一个模板类,因为我不知道如何迭代模板类。当类型不是静态已知时,就像基类指针容器的情况一样,很少有机会进行静态多态性。一个简单的旧运行时多态性a.k.a.OOP是正确的。这并不排除静态多态性phism在程序的其他部分。嗯,我会尝试这个实现,但是如果我必须在程序的这个特定部分执行运行时多态性,它会有点达不到目的。我认为这是不可行的(至少我不知道任何可能的解决方案)通过这个实现,我将如何调用正确的访问函数?考虑到我有3个访问者类可以被传递给接受函数。在接受函数中,我希望调用访问者访问函数,但是我不知道我现在正在操作哪个访问者。吃东西,作为静态访客的一部分,他们不共享父母
#include <iostream>
#include <tuple>
#include <type_traits>
using namespace std;


template<typename Derived>
class BaseData {
public:
    template<typename Visitor>
    void accept(Visitor &v){
         static_cast<Derived*>(this)->accept(v);
    }
};

class DerivedBaseData1: BaseData<DerivedBaseData1> {
public:
    template<typename Visitor>
    void accept(Visitor &v){
        std::cout << "DerivedBaseData1: accepting visitor " << v << std::endl;
    }    
};
class DerivedBaseData2: BaseData<DerivedBaseData2> {
public:
    template<typename Visitor>
    void accept(Visitor &v){
        std::cout << "DerivedBaseData2: accepting visitor " << v << std::endl;
    }    
};

namespace impl {

    template <size_t N> 
    struct num2type {};

    template <size_t Idx, typename T, typename Visitor>
    void accept_impl(Visitor &v, T &&collection, num2type<Idx>) {
        // run accept on current object
        auto &object = std::get<Idx>(collection);
        object.accept(v);
        // move iteration forward
        accept_impl(v, std::forward<T>(collection), num2type<Idx - 1>{});
    }

    template <typename T, typename Visitor>
    void accept_impl(Visitor &v, T &&collection, num2type<0>) {
        // run accept on current object
        auto &object = std::get<0>(collection);
        object.accept(v);
    }
}

template<typename ...Ts, typename Visitor>
void accept(Visitor &v, std::tuple<Ts...> &&collection) {
    using T = decltype(collection);
    impl::accept_impl(v, std::forward<T>(collection), impl::num2type<std::tuple_size<std::decay_t<T>>::value - 1>{});
}


int main() {
    using visitor_type = int;
    visitor_type visitor = 42;

    DerivedBaseData1 a1, a3;
    DerivedBaseData2 a2;
    accept(visitor, std::tie(a1, a2, a3));

    return 0;
}