Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;多态性+;用于选择返回类型的模板成员函数。怎么做?_C++_Templates_Virtual Functions_Traits - Fatal编程技术网

C++ C++;多态性+;用于选择返回类型的模板成员函数。怎么做?

C++ C++;多态性+;用于选择返回类型的模板成员函数。怎么做?,c++,templates,virtual-functions,traits,C++,Templates,Virtual Functions,Traits,我想为对象分派实现一个类层次结构。不同的类分派不同的元素,每个类可以分派其表示为不同数据类型的元素 通过一个(错误的)例子可以更好地理解它。如果允许使用虚拟函数模板,我希望这样做: class Dispatcher { template <class ReturnType> virtual ReturnType getStuffAs(); }; 类调度器{ 模板 虚拟返回类型getStuffAs(); }; 这样我就可以实现子类,如下所示: class CakeD

我想为对象分派实现一个类层次结构。不同的类分派不同的元素,每个类可以分派其表示为不同数据类型的元素

通过一个(错误的)例子可以更好地理解它。如果允许使用虚拟函数模板,我希望这样做:

class Dispatcher {
    template <class ReturnType>
    virtual ReturnType getStuffAs();
};
类调度器{
模板
虚拟返回类型getStuffAs();
};
这样我就可以实现子类,如下所示:

class CakeDispatcher : public Dispatcher {
    template <>
    virtual Recipe getStuffAs(){ ... }
    template <>
    virtual Baked getStuffAs(){ ... }
};
class DonutDispatcher : public Dispatcher {
    template <>
    virtual Frozen getStuffAs(){ ... }
    template <>
    virtual Baked getStuffAs(){ ... }
}
class CakeDispatcher:公共调度程序{
模板
虚拟配方getStuffAs(){…}
模板
虚拟烘焙getStuffAs(){…}
};
类DonutDispatcher:公共调度程序{
模板
虚拟冻结getStuffAs(){…}
模板
虚拟烘焙getStuffAs(){…}
}
以便稍后我可以执行以下操作:

void function( Dispatcher * disp ) {
    // Works for Donut and Cake, but result will be a different Baked object
    Baked b = disp->getStuffAs<Baked>();
    // works if disp points to a DonutDispatcher
    // fails if it is a CakeDispatcher
    // can be compiling/linking time error or runtime error. I don't care
    Frozen f = disp->getStuffAs<Frozen>(); 
}
void函数(调度程序*disp){
//适用于甜甜圈和蛋糕,但结果将是不同的烘焙对象
烘焙b=disp->getStuffAs();
//如果disp指向DonutDispatcher,则此选项有效
//如果是CakeDispatcher,则失败
//可能是编译/链接时间错误或运行时错误。我不在乎
冻结f=disp->getStuffAs();
}
要求/限制:

  • 所有可能的返回类型事先都不知道。这就是我“需要”模板的原因
  • 每个类只能提供一些返回类型
  • 类必须有一个共同的祖先,这样我就可以通过指向父类的指针存储对象,并通过该指针调用函数
  • 编辑:我不能使用C++11功能,但我可以使用boost库
我考虑过但不是解决办法的事情:

  • 显然,虚拟模板功能
  • :打破共同祖先的条件
  • 使用某种类型的traits类包含子类的功能,但它不起作用,因为父类中的非虚拟实现无权访问此信息
我可能会在父类中存储一些typeid信息,这些信息是由子类在构造时传递的。这使得非虚拟父分派方法能够将自身动态强制转换为子类型。。。但它看起来像地狱一样丑陋,我不知道这是否会导致某种循环引用问题

class Dispatcher {
private: 
    typeid(?) childType;
public:
    Dispatcher(typeid childT) : childType(childT) {}

    // NOT VIRTUAL
    template <class ReturnType>
    ReturnType getStuffAs()
    {
        // or something equivalent to this cast, which I doubt is a correct expression
        return dynamic_cast<childType *>(this)->childGetStuffAs<ReturnType>();
    }
};
类调度器{
私人:
typeid(?)childType;
公众:
调度程序(typeid childT):childType(childT){
//不是虚拟的
模板
ReturnType getStuffAs()
{
//或者类似于这个角色的东西,我怀疑这是一个正确的表达
返回dynamic_cast(this)->childGetStuffAs();
}
};
然后子类将实现childGetStuffAs函数,这些函数也不是虚拟的。 我读过5-10个相关问题,但提供的解决方案似乎都不适合这个问题

你们谁能想出更好的解决办法? 是否有解决此问题的标准模式/技术

编辑:真正的问题 在实际问题中,我有一些物理模型,其属性可以用多种方式表示:函数、矩阵、概率分布、多项式和其他一些(例如,非线性系统可以表示为函数,但不能表示为矩阵,而线性系统可以转换为两者)

还有一些算法可以模糊地使用这些模型,但它们可能需要某些模型特征的特定表示。这就是“getStuffAs”函数的原因。整个想法有点复杂——这里解释得太多了——但我可以保证在这种情况下,接口定义得很好:输入、计算和输出

我的意图是,假设预先完全定义了可能的表示形式的数量,并使产品能够转换为无法修改的现有类型/类,使之成为可能。
然而,我开始意识到,用一种简单的方法来说,这确实是不可能的——我不想只为这个问题编写一个库。

我的解决方案是循环模板和菱形继承的组合。 至少它起作用了。:)

#包括
类调度器
{
公众:
模板
T getStuff()
{
返回T();
}
};
模板
类填充器:公共调度程序
{
公众:
模板
TT getStuff(){
返回重新解释(本);
}
};
班级蛋糕{
公众:
蛋糕(){}
作废打印()
{
std::cout
#包括
//作为类型标识符
结构材料{
虚拟void foo(){}
};
模板
struct stuff\u inh:stuff{
};
结构调度器{
模板
T*getStuffAs(){
返回(T*)((getStuffAsImpl(newStuff_inh()))));
}
虚拟void*getStuffAsImpl(void*)=0;
虚拟void type(){printf(“type::dispatcher\n”);}
};
结构蛋糕:公共调度程序{
void*getStuffAsImpl(void*p){
stuff*s=静态_铸造(p);
printf(“蛋糕impl\n”);
如果(动态_转换==NULL){
扔“坏石膏”;
}
退货(作废*)(新蛋糕());
}
虚拟void type(){printf(“type::Cake\n”);}
};
结构兔:公共调度程序{
void*getStuffAsImpl(void*p){
stuff*s=静态_铸造(p);
printf(“兔impl\n”);
如果(动态转换)!=NULL{
返回(无效*)(新兔子());
}
如果(动态_转换)!=NULL,则为else{
退货(作废*)(新蛋糕());
}
否则{
扔“坏石膏”;
}
}
虚拟void type(){printf(“type::Rabbit\n”);}
};
void foo(调度员*d){
d->getStuffAs()->type();
d->getStuffAs()->type();
}
int main(){
兔子*r=新兔子;
富(r),;
蛋糕*c=新蛋糕;
傅(丙),;
}
我不确定这个丑陋的解决方案是否正确,希望它能对您有所帮助。>\u template+virtua
#include <iostream>

class Dispatcher
{
public:
  template<class T>
  T getStuff()
  {
    return T();
  }
};

template<class T>
class Stuffer : public Dispatcher
{
public:
  template<class TT=T>
  TT getStuff(){
    return reinterpret_cast<TT>(this);
  }
};

class Cake{
public:
  Cake(){}

  void print()
  {
    std::cout << "Cake" << std::endl;
  }
};

class Recipe
{
public:
  Recipe(){}

  void print()
  {
    std::cout << "Recipe" << std::endl;
  }
};

class CakeRecipe : public Stuffer<Cake>, public Stuffer< Recipe >
{
public:
};

int main()
{
  Dispatcher* cr = reinterpret_cast<Dispatcher*>(new CakeRecipe());
  cr->getStuff<Cake>().print();
  cr->getStuff<Recipe>().print();

  getchar();
  return 1;
}
#include <cstdio>
// as a type identifier
struct stuff {
    virtual void foo() {}
};

template <typename T>
struct stuff_inh : stuff {
};

struct Dispatcher {
    template <typename T>
        T* getStuffAs() {
            return (T*)((getStuffAsImpl( new stuff_inh<T>() )));
        }

    virtual void* getStuffAsImpl(void*) = 0;
    virtual void type() {printf("type::dispatcher\n");}
};

struct Cake : public Dispatcher {
    void* getStuffAsImpl(void* p) {
        stuff* s = static_cast<stuff*>(p);
        printf("cake impl\n");
        if (dynamic_cast<stuff_inh<Cake>*>(s) == NULL) {
            throw "bad cast";
        }
        return (void*)(new Cake());
    }
    virtual void type() {printf("type::Cake\n");}
};

struct Rabbit : public Dispatcher {
    void* getStuffAsImpl(void* p) {
        stuff* s = static_cast<stuff*>(p);
        printf("rabbit impl\n");
        if (dynamic_cast<stuff_inh<Rabbit>*>(s) != NULL) {
            return (void*)(new Rabbit());
        }
        else if (dynamic_cast<stuff_inh<Cake>*>(s) != NULL) {
            return (void*)(new Cake());
        }
        else {
            throw "bad cast";
        }
    }
    virtual void type() {printf("type::Rabbit\n");}
};

void foo(Dispatcher* d) {
    d->getStuffAs<Cake>()->type();
    d->getStuffAs<Rabbit>()->type();
}


int main() {
    Rabbit* r = new Rabbit;
    foo(r);
    Cake* c = new Cake;
    foo(c);
}