2015-06-07 73 views
3

請看下面的例子:曖昧的轉換,從qm鑄造運營商總是模棱兩可

struct m 
{ 
    m(int) { } 
}; 

class q 
{ 
public: 

    int i; 

    q(int i) 
    { 
     this->i = i; 
    } 

    operator double() 
    { 
     return (double) i; 
    } 

    operator m() 
    { 
     return (m)i; 
    } 
}; 

int main() 
{ 
    q x(1); 
    (m)x; // error: ambiguous 
} 

它當我打電話鑄造失敗。爲什麼這樣?我真的不明白。我明確添加了一個鑄造操作符m!爲什麼這應該是模糊的?但是,如果我將演員陣容刪除至double,則可以使用。爲什麼這很重要?我該怎麼做我想做的事?

+0

它也可以,如果我刪除投翻一番,但反過來就意味着損失性能的時候我只是想轉換爲雙。 –

+0

如何定義「mpf_class」?它是什麼? – user35443

+0

mpf_class是GMP(Gnu Multiple Precision)庫中的主要類之一。 –

回答

2

考慮可能的路徑,編譯器可以當你拿:

m temp__(x); 

有三個相關的構造函數:

m(int);  // (A) 
m(const m&); // (B) 
m(m&&);  // (C) 

我們可以稱之爲通過x --> double --> int(A),這是一個定義用戶轉換順序。

我們可以通過x --> m調用(B)(C),這也是一個用戶定義的轉換序列。

如果用戶定義的轉換序列最終調用相同的構造函數,則它們只能作爲另一個偏好。但在這種情況下,他們不這樣做 - 所以編譯器無法將其中一個選擇爲另一個。因此,含糊不清。

你的選擇將是

  • 打電話給你的運營商直接(或使其與一些名稱的功能);或
  • 使q繼承自m - 導出到基準的轉換將優於用戶定義的轉換序列;或
  • 使兩個轉換運算符explicit - 在這種情況下,將只有一個可行的候選人開始,所以不會有歧義。
0

當我編譯程序使用g ++ 5.1,我得到:

/home/imk/develop/so/mpf_cast/main.cpp:35:25: error: call of overloaded ‘__gmp_expr(q&)’ is ambiguous 
    cout << (mpf_class) x << endl; 
         ^
/home/imk/develop/so/mpf_cast/main.cpp:35:25: note: candidates are: 
In file included from /home/imk/develop/so/mpf_cast/main.cpp:2:0: 
/usr/include/gmpxx.h:1883:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(double) 
    __gmp_expr(double d) { mpf_init_set_d(mp, d); } 
^
/usr/include/gmpxx.h:1880:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(float) 
    __gmp_expr(float f) { mpf_init_set_d(mp, f); } 
^
/usr/include/gmpxx.h:1876:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(long unsigned int) 
    __gmp_expr(unsigned long int l) { mpf_init_set_ui(mp, l); } 
^
/usr/include/gmpxx.h:1873:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(long int) 
    __gmp_expr(signed long int l) { mpf_init_set_si(mp, l); } 
^
/usr/include/gmpxx.h:1869:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(short unsigned int) 
    __gmp_expr(unsigned short int s) { mpf_init_set_ui(mp, s); } 
^
/usr/include/gmpxx.h:1866:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(short int) 
    __gmp_expr(signed short int s) { mpf_init_set_si(mp, s); } 
^
/usr/include/gmpxx.h:1862:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(unsigned int) 
    __gmp_expr(unsigned int i) { mpf_init_set_ui(mp, i); } 
^
/usr/include/gmpxx.h:1859:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(int) 
    __gmp_expr(signed int i) { mpf_init_set_si(mp, i); } 
^
/usr/include/gmpxx.h:1855:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(unsigned char) 
    __gmp_expr(unsigned char c) { mpf_init_set_ui(mp, c); } 
^
/usr/include/gmpxx.h:1852:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(signed char) 
    __gmp_expr(signed char c) { mpf_init_set_si(mp, c); } 
^
/usr/include/gmpxx.h:1837:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(const __gmp_expr<__mpf_struct [1], __mpf_struct [1]>&) 
    __gmp_expr(const __gmp_expr &f) 
^

問題投表達(mpf_class) x需要mpf_classtypedef __gmp_expr<mpf_t, mpf_t> mpf_class) 將要從q構成。所以你也可以考慮

q x(1); 
mpf_class m(x); 

這會引發相同的診斷。

爲什麼施工模糊不清?這是因爲: -

  • 還有就是,當然,沒有這樣的構造如mpf_class(q const &)
  • 因此,轉換是必需的,如果存在的話,從q在診斷中列舉的其他11種類型之一, ,從中可以構建出mpf_class可以
  • 但也有這樣的轉換,每個不如對方,這要歸功於 兩個轉換操作符與您所提供q

轉換operator double()能滿足第一個11個構造 的和operator mpf_class()能夠滿足最後一個。編譯器沒有基礎 喜歡這些構造函數。

如果你犧牲了一個或其他演員,這個問題就會消失。 如果你都必須有他們,那麼你也可以通過使二者 explicit的解決這個問題,所以,除非它被顯式調用編譯器將不考慮調用轉換:

explicit operator double() 
{ 
    return (double)i; 
} 
explicit operator mpf_class() 
{ 
    return (mpf_class)i; 
} 

這時你會發現,例如:

int main() 
{ 
    q x(1); 
    mpf_class mpf(x); // via `explicit operator mpf_class()` 
    double d(x); // via `explicit operator double()` 
    // d = q(2); <- does not compile 
    d = static_cast<double>(q(2)); 
    // mpf = q(2); <- does not compile 
    mpf = static_cast<mpf_class>(q(2)); 
    return 0; 
} 

順便說一句:

  • 演員運營商應該是const
  • 在一個函數中,當存在隱式轉換時,將返回值轉換爲 返回類型是非常繁瑣的。

因此:

explicit operator double() const 
{ 
    return i; 
} 
explicit operator mpf_class() const 
{ 
    return i; 
}