2009-09-15 104 views
3

我有一個程序需要設置程序執行時的矢量類型(根據配置文件中的值)。在運行時設置矢量類型

我已經試過這樣:

int a = 1 

if(a == 1) vector<int> test(6); 
else vector<unsigned int> test(6); 

test.push_back(3); 

但是這給了我:

Error 1 error C2065: 'test' : undeclared identifier 

我不完全知道爲什麼,但我認爲這是因爲矢量實際上不是在編譯的決定因此編譯器無法在編譯其餘代碼時使用它。

有沒有一種方法可以在運行時確定類似於我上面嘗試過的向量類型? 我試圖在if之外創建一個版本,然後刪除它並重新寫入IF中的新版本。但是,這感覺不對,我無法讓它工作。 謝謝。

回答

13

它不起作用的原因是你分別在if和else塊內聲明矢量,所以一旦塊結束,它們就超出範圍。

有沒有一種方法可以在運行時確定類似於我上面嘗試過的向量類型?

不,變量的類型必須在編譯時已知。您唯一的選擇是將行test.push_back(3)以及任何後面的代碼訪問test放入if-和else-block中,或避免將代碼複製到第二個模板化函數中。這可能是這樣的:

template <class T> 
do_something_with_test(vector<T>& test) { 
    test.push_back(3); 
    // work with test 
} 

void foo() { 
    int a = 1 

    if(a == 1) { 
     vector<int> test(6); 
     do_something_with_test(test); 
    } 
    else { 
     vector<unsigned int> test(6); 
     do_something_with_test(test); 
    } 
} 
+0

謝謝。我明白你在說什麼。我將研究這一點,也許把我所有的代碼放在矢量類型的決策中,就像你所建議的模板化函數。 – Columbo 2009-09-15 09:50:30

+1

這工作,採取了一些改變周圍埠,這是排序它。謝謝。 – Columbo 2009-09-15 11:03:17

4

您得到的錯誤的確切原因對初學者來說是微妙的原因,它涉及您正在創建的變量test的範圍。簡而言之,您在if語句內部創建矢量,但在您打算使用它時,它不再存在,因爲它已經超出了範圍。

我已經用方括號重新格式化了你的代碼,使這個效果更明顯。請注意,我的版本在語義上與您的版本相同,並且會出現相同的錯誤。

if(a == 1) 
{ 
    vector<int> test(6); 
} 
else 
{ 
    vector<unsigned int> test(6); 
} 

test.push_back(3); 

這就是說,你正在嘗試做似乎有點不可思議,而且我想知道你的最終目標是什麼。這並不是說沒有辦法做你想做的事情,但我需要知道你的成功標準,然後才能提出更合適的方法。

+0

謝謝。注意:顯示的代碼只是爲了解釋...實際的程序處理二進制數據,並且可以在32或64位模式下運行。矢量類型需要改變,以保持指向一個類(實際上包含數據)的64或32位大小的指針。這個類是一個模板類,所以我的矢量類型決定了我的模板類的類型。我明白了你對範圍的看法。目前我正在嘗試查看是否有可能在if之外設置向量,然後在if循環中將其強制轉換爲64位。 – Columbo 2009-09-15 09:39:41

+2

你爲什麼要寫兩個代碼來處理32位或64位?你用來控制32/64版本的編譯器開關將決定指針的大小和類型 - 只有一個指向你類的指針向量。矢量測試; – JBRWilkinson 2009-09-15 10:56:28

3

我不知道你爲什麼需要這一點,但我建議你嘗試使用聯合的載體來解決問題,這樣的事情

union DataType 
{ 
    int intVal; 
    unsigned uintVal; 
} 
std::vector<DataType> vec; 

或者更優雅的方式是使用boost::variant而不是聯合。也許如果你給我們提供關於你的問題的更多細節,你會得到更好的結果。

祝你好運!

+0

修復了您的格式,以便「」出現在「向量」中。 – 2009-09-15 11:07:29

-1

在您的示例中,您的if語句的每個分支中都創建了變量test的獨立實例,每個分支都立即超出範圍。所以當編譯器得到test.push_back(3);時,範圍內沒有test變量,因此是錯誤。

爲了解決你的問題,你無法抗拒的類型系統:假設intunsigned int是實際類型的問題,你一定會覺得很更好使用vector<int>貫穿始終,假設你實際上並不需要完整無符號整數的範圍。

0

如果你真的需要一個多態類型,也許你可以看看boost :: variant類或類似的東西;
這是爲了模仿C++中動態語言的一些行爲而設計的,通常用於連接(或實現)它們。你可以創建一個「向量< Variant> a」和a.push_back(Variant((unsigned int)..)。推送的值的構造函數需要編譯時間類型。

也可以創建矢量化的變體類,如果你期望值是同質的,它存儲整個集合的類型信息。

但是,如果沒有這樣的機制,你很可能實現期望的最終結果,重新編寫程序以避免運行時類型檢查可能(這很可能會否定使用C++優於其他語言的一些好處)。

你湊合ld將類型相關部分寫爲模板(如上所示),並根據選中的&調度一次的配置文件設置選擇替代代碼路徑。這種類型的編碼在C++ 0x中使用'auto'和decltype()函數也稍微容易一些。

無符號與有符號值的具體情況涉及允許多出一個聽起來不尋常的位或與增加的複雜度相比邊際益處,但我可以輕易想象一個想要一個可以在單精度浮點數和雙精度浮點數之間切換的實現例。

另一個簡單的選擇是爲該類型進行編譯時設置(例如作爲構建設置或生成文件中的定義引入),然後分發程序的多個版本,這在某些情況下可能有意義。但是,已經提出的模板更可能是最有用的選項。