2016-08-05 42 views
2

假設我有一個Matrix類,我想初始化有兩種方式我Matrix對象:如何使用非嵌套和嵌套的initializer_list參數來區分兩個重載函數?

Matrix a = {1,2,3} // for a row vector 

Matrix b = {{1,2,3},{4,5,6},{7,8,9}} // for a matrix 

結果,我實現了兩個拷貝構造函數如下

class Matrix { 
private: 
    size_t rows, cols; 
    double* mat; 
public: 
    Matrix() {} 
    Matrix(initializer_list<double> row_vector) { ... } 
    Matrix(initializer_list< initializer_list<double> > matrix) { ... } 
    ... 
} 

無論我如何更改界面,例如添加explicit關鍵字或將嵌套版本更改爲Matrix(initializer_list< vector<double> > matrix)。它總是會引起歧義這兩種情況之間:

Matrix a = {1,2,3};n 
Matrix b = {{1}, {2}, {3}}; 

我不是很熟悉,如直接/拷貝初始化或隱式類型轉換的東西。有沒有解決這個問題的方法?

+0

您是否試圖根據輸入調整您的矩陣大小?例如,你是否期望'{1,2,3}'產生一個3x1向量,並且'{{1,2,3},{4,5,6},{7,8,9}}'產生一個3x3矩陣? –

+0

@JonathanMee絕對。 – pedim

+0

@pedim所以有點令人驚訝,如果你使用Visual Studio *,它會*選擇第三個構造函數。我在這裏打開一個關於它的問題:http://stackoverflow.com/q/38795374/2642059 –

回答

2

嗯,這裏是一個非常骯髒的伎倆:

#include <iostream> 
#include <initializer_list> 

struct Matrix 
{ 
    template<class = void> Matrix(std::initializer_list<double>) { std::cout << "vector\n"; } 
    Matrix(std::initializer_list<std::initializer_list<double>>) { std::cout << "matrix\n"; } 
}; 

int main() 
{ 
    Matrix a = {1, 2, 3}; 
    Matrix b = {{1}, {2}, {3}}; 
    (void)a; (void)b; 
} 

兩個重載無法區分基礎上轉換,因此我們依靠重載決策過程的後續步驟:非模板函數優於模板專業化。

+1

_Disgraceful!_我喜歡它。我也不知道未命名的模板參數是被允許的,因爲我從來沒有使用過這種東西......謝天謝地...... _yet_。 ;-) –

0

爲什麼不只是創建一個構造函數,它需要一個矩陣,創建一個私有函數副本,並在內部副本中檢查row_vector。

private void Matrix::copy(const Matrix &matrix) 
{ 
    if (matrix.rows == 1) 
    { 
     //row vector stuff here 
    } 
    else if (matrix.cols == 1) 
    { 
     //col vector stuff here 
    } 
    else 
    { 
     //matrix stuff here 
    } 
} 
+0

但我的目的是接收兩種初始值設定項。我怎樣才能使用一個構造函數來處理兩種類型的對象? – pedim

+0

爲什麼不初始化像這樣的行向量: Matrix a = {{1,2,3}} 刪除您的某個構造函數的需要。 – Richard

+0

爲了方便,OP希望能夠接收兩種不同類型的參數,而不是用一種類型做不同的事情。這並沒有根據請求區分參數類型,也沒有努力解釋這個私有函數如何被使用/有用......並且甚至不會進行編譯:您或者忘記了冒號(和換行符)重新思考Java/C#。 –

4

有沒有解決方案,將明確地在每一種情況下工作。但是,您可以創建消除案例歧義的方法:

template<typename T> 
auto il(std::initializer_list<T> the_il) -> std::initializer_list<T> { return the_il; } 

Matrix b = {il({1}), {2}, {3}}; 

但是,我個人建議您明確說明。如果用戶想要一個包含一個行的矩陣,那麼它應該看起來像一個包含矩陣一行,而不是像一個載體:

Matrix a = {{1,2,3}}; 

所以我建議乾脆拋棄了第一個重載。