2015-05-29 52 views
1

我使用的是有兩個模板參數傳遞恆定值到模板

itk::Image<PIXELTYPE,DVALUE> 

在讀我的形象會得到有關圖像的類型和尺寸信息的時間模板類。由於有類型的11個可能的值和維度的3個值(2,3,4)每次我讀取的圖像,並具有以應用我做它的操作如下:

std::string type = IOBase->GetComponentTypeAsString(IOBase->GetComponentType()); 
const unsigned int dim = IOBase->GetNumberOfDimensions(); 

if(dim ==3) 
{ 
    if(type == "unsigned_char") 
    { 
     typedef itk::Image<unsigned char,3> ImageType; 
     //apply operation 
    } 
    else if(type == "char") 
    { 
     typedef itk::Image< char,3> ImageType; 
     //apply operation 

    } 
    else if(type ==....so on 
} 

然後我再次有要做到這一點dim=4dim ==2 它增加了太多的代碼。所以,我想通過把它的值,以避免在弱光環境,如果其他檢查:

std::string type = IOBase->GetComponentTypeAsString(IOBase->GetComponentType()); 
const unsigned int dim = IOBase->GetNumberOfDimensions(); 

if(type == "unsigned_char") 
{ 
      typedef itk::Image<unsigned char,3> ImageType; 

我有以下情況:

const unsigned int dimension = 3; 
    itk::Image<unsigned char, dimension > image; 
在執行時

在這裏,我必須要找到將是什麼類型和尺寸那麼圖像將被創建。當我運行上面的代碼時,它正在工作。但是,當我試圖做到這一點的方式如下:

const unsigned int dimension = FunctionGetDimension(); 
itk::Image<unsigned char, dimension > image; 

它不工作,即使我做的FunctionGetDimension()返回值,爲const它無法正常工作。有沒有辦法做到這一點?

回答

2

模板參數在編譯時應該已知,不可能在運行時指定它們。即使您的dim是恆定的,它在編譯時也是未知的。

因此,無論如何,您需要一些或多或少的手工製作邏輯來創建您需要的Image對象。通常的做法是建立一個工廠。

最簡單的工廠類型是我認爲你已經擁有的 - if/else if/else if ...子句的鏈,每個子類都返回一個不同類型的對象。你只應更好地將它開了一個單獨的功能類似以下內容:

// I assume that itk::Image subclasses a non-template BasicImage 
// if this is not the case, you will need some kind of a wrapper 
// you should also return unique_ptr or its friends instead of raw pointer 
BasicImage* createImage(int dim, std::string type) { 
    if (dim == 3) { 
     if (type == "unsigned_char") 
      return new itk::Image<unsigned char, 3>(); 
     else if... 
    } else if... 
} 

這方面有更先進的技術:代替硬編碼的if/else鏈,你可以把它的一類,並保持std::map的創建需要的對象的函數,並有對象自己註冊它,請參閱"Factory Pattern""Factory Pattern in C++"。這不會節省太多的編碼,因爲您仍然可以使用代碼來註冊每個班級,但是您可以將此註冊移動到更好的位置並獲得更多優勢。

但是,我不會過分複雜的事情。只要您瞭解工廠的工作方式,您就可以從帶有硬編碼if/else鏈的簡單工廠開始,然後在需要時使用map和註冊方式切換到工廠,而無需更改工廠的客戶端界面。請提前考慮這個界面。相反,如果你有很多模板的變體,你不僅需要執行std::map,但你需要讓編譯器爲你處理註冊。爲此,您可能需要查看"Subscribing Template Classes with Object Factories in C++",它描述了一個與您非常相似的案例,並添加了一些更高級的方法。

+1

要使用工廠,你需要一個類型擦除版本的Image對象。 – petersohn

+0

@petersohn,我對itk一無所知,但是沒有這種類型擦除的基類嗎?如果沒有,那麼我認爲不可能有一個'itk :: Image'對象和運行時確定的尺寸/類型,因爲在編譯時應該知道對象類型。同時,可能會在'Image'周圍製作一個包裝類,讓工廠以這種方式工作。 – Petr

+2

我也不知道它。但是,當然,如果沒有基類,你可以創建這樣一個包裝器。 – petersohn