2013-03-03 74 views
0

我想找到一個類層次結構,它允許爲處理器寄存器和操作執行佔位符。它也應該允許常量在運行時摺疊。爲了簡單起見,我只會看一個操作,這裏是乘法。佔位符和常量應該可以統一訪問,即有一個共同的基類。避免打開類型以允許不斷摺疊

下面的代碼定義了以下類:

class A:爲佔位符(寄存器)和常量

基類

class B:對於一個寄存器將保持器(它的結構保持它的名稱)

class C:基本所有常量

class CIint不斷

class CFfloat恆定

#include <iostream> 
#include <memory> 
#include <cassert> 

class A { 
public: 
    virtual ~A(){} 
}; 

class B : public A { 
}; 

class C : public A {}; 

class CI : public C { 
public: 
    typedef int Type_t; 
    int getValue() {return 1;} 
}; 

class CF : public C { 
public: 
    typedef float Type_t; 
    float getValue() {return 1.1;} 
}; 




typedef std::shared_ptr<A> Aptr; 
typedef std::shared_ptr<B> Bptr; 
typedef std::shared_ptr<C> Cptr; 
typedef std::shared_ptr<CI> CIptr; 
typedef std::shared_ptr<CF> CFptr; 


template<class T, class T2> struct promote {}; 
template<> struct promote<float,int> { typedef float Type_t; }; 
template<> struct promote<float,float> { typedef float Type_t; }; 
template<> struct promote<int,float> { typedef float Type_t; }; 
template<> struct promote<int,int > { typedef int Type_t; }; 


template<class T1, class T2> 
typename promote<typename T1::element_type::Type_t, 
     typename T2::element_type::Type_t>::Type_t 
mul_const(const T1& c1 , const T2& c2) 
{ 
    std::cout << c1->getValue() * c2->getValue() << "\n"; 
    return c1->getValue() * c2->getValue(); 
} 



template<class T> 
std::shared_ptr<T> get(const Aptr& pA) { 
    return std::dynamic_pointer_cast<T>(pA); 
} 


Aptr create_A(float f) { return std::make_shared<A>(); } 
Aptr create_A(int i) { return std::make_shared<A>(); } 


Aptr mul_const(const Cptr& cp1 , const Cptr& cp2) 
{ 
    if (auto c1 = get<CI>(cp1)) 
    if (auto c2 = get<CF>(cp2)) { 
     return create_A(mul_const(c1,c2)); 
    } 
    if (auto c1 = get<CF>(cp1)) 
    if (auto c2 = get<CI>(cp2)) { 
     return create_A(mul_const(c1,c2)); 
    } 
    if (auto c1 = get<CI>(cp1)) 
    if (auto c2 = get<CI>(cp2)) { 
     return create_A(mul_const(c1,c2)); 
    } 
    if (auto c1 = get<CF>(cp1)) 
    if (auto c2 = get<CF>(cp2)) { 
     return create_A(mul_const(c1,c2)); 
    } 
    assert(!"oops"); 
} 



Aptr mul(const Aptr& pA1, const Aptr& pA2) 
{ 
    if (auto c1 = get<C>(pA1)) 
    if (auto c2 = get<C>(pA2)) 
     { 
    return mul_const(c1,c2); 
     } 
} 


int main() 
{ 
    Aptr pA1(new CF); 
    Aptr pA2(new CI); 

    Aptr result = mul(pA1, pA2); 
} 

我正在與上述代碼遇到的問題是該函數Aptr mul_const(const Cptr& cp1 , const Cptr& cp2)。它基本上包含了所有可能的常量類型組合的類型切換。它有效,但我想知道這是否可以更優雅地完成?

+0

'在運行時常量摺疊?這是一個編譯時間的概念。 – 2013-03-03 00:07:31

+0

那麼,你根據編譯時的類型生成它的指令。但這些值僅在運行時纔可用。你可以看到'CI'擁有'int'。這是其結構的一部分。 (爲簡單起見,它被設置爲1) – ritter 2013-03-03 00:10:27

+0

這裏的問題是從運行時切換到編譯時多態性。對於給定的類層次結構,你需要這個。問題是可以做得更好嗎? – ritter 2013-03-03 00:29:35

回答

1

我想你可以做什麼編譯器,並將其他參數轉換爲浮動當一個是浮動。您可能需要一個新功能來完成轉換,並且需要一個「isFloat」(或「isInt」)。我不相信它給你多少好處,真的...

// Add two virtual member functions here: 
class C : public A { 
    public: 
     virtual bool isInt() = 0; 
     virtual float getAsFloat() = 0; 
}; 

然後實現:

class CI : public C { 
public: 
    typedef int Type_t; 
    int getValue() {return 1;} 
    float getAsFloat() { return getValue(); } 
    bool isInt() { return true; } 
}; 

class CF : public C { 
public: 
    typedef float Type_t; 
    float getValue() {return 1.1;} 
    float getAsFloat() { return getValue(); } 
    bool isInt() { return false; } 
}; 

現在,您mul_const變爲:

Aptr mul_const(const Cptr& cp1 , const Cptr& cp2) 
{ 
    if (cp1.isInt() && cp2.isInt()) 
    { 
    CIptr c1 = get<CI>(cp1)); 
    CIptr c2 = get<CI>(cp2)); 
    std::cout << c1->getValue() * c2->getValue() << "\n"; 
    return CIptr(c1->getValue() * c2->getValue()); 
    } 
    else 
    { 
    std::cout << cp1->getAsFloat() * cp2->getAsFloat() << "\n"; 
    return CFptr(cp2->getAsFloat() * cp2->getAsFloat()); 
    } 
    // This becomes unreachable... Probably OK to delete. 
    assert(!"oops"); 
} 

[我想幾個模板部分可以刪除...]

+0

它的好處在於它消除了對'struct promote'的需求。 – ritter 2013-03-03 00:41:18

+0

是的,我認爲這也是一個好處。我認爲它使代碼更容易閱讀[我很快就迷失在複雜的模板代碼中 - 可能是因爲我沒有做過那麼多的模板編碼...] – 2013-03-03 00:48:14