2011-12-09 4 views
4

gettersがconstの場合、以下のコードが(VS2010)をコンパイルしない理由を理解できますか?資格調整(const/volatile)があいまいさを引き起こしている可能性があります

は、ここでのテストコードです:

#include <boost/system/error_code.hpp> 

class socket { 
public: 

    // setter - throw exception version 
void non_blocking(bool mode) 
    { 
     // ... 
    } 

    // getter - error code version  
    bool non_blocking(boost::system::error_code& ec) const 
    { 
     // ... 
    } 

    // setter - error code version 
void non_blocking(bool mode, boost::system::error_code& ec) 
    { 
     // ... 
    } 

    // getter - throw exception version  
    bool non_blocking() const 
    { 
     // ... 
    } 
}; 

int main() 
{ 
    socket s; 
    boost::system::error_code ec; 
    bool result = s.non_blocking(ec); 

    return 0; 
} 

私はそのブースト::システムを知っている:: ERROR_CODEはBOOLに変換可能であるが、constのは、あいまいさを引き起こす理由を理解することはできません。ここでVS2010からのエラーメッセージがあります:

1>c:\projects\pcap++\trunk\main.cpp(145): error C2666: 'socket::non_blocking' : 2 overloads have similar conversions 
1>   c:\projects\pcap++\trunk\main.cpp(134): could be 'bool socket::non_blocking(boost::system::error_code &) const' 
1>   c:\projects\pcap++\trunk\main.cpp(129): or  'void socket::non_blocking(bool)' 
1>   while trying to match the argument list '(boost::system::error_code)' 
1>   note: qualification adjustment (const/volatile) may be causing the ambiguity 
+1

's'が' const'の場合、あいまいさはありませんでしたが、そうではなく、両方の関数を使うことができました。私はなぜあなたが最初の関数( 'bool'を持つ関数)を持っているのだろうと思っています。 – Shahbaz

+0

これは奇妙に見えます。 'bool non_blocking'の中で' void non_blocking'を呼び出していますか? –

+1

@Shahbaz: 'bool result = s.non_blocking(ec);'はどうですか?これはどうやって曖昧ですか?コンパイラは 'void non_blocking(bool)'とマッチできないことは明らかです。 –

答えて

1

を、2つのオーバーロードのパラメータリストはclass socket &, boolconst class socket &, boost::system::error_code &です。

呼び出しパラメータが最初の過負荷と一致するclass socket &, boost::system::error_code &

あり、以下の変換が必要である:C++ 0X 13.3.3p1で

1. 
class socket &    -> no conversion 
bool      -> user defined conversion 
2. 
class socket &    -> qualification conversion 
boost::system::error_code & -> no conversion 

を:

は(ICSI定義しますF)が次のように定義される:

- Fが静的メンバー関数である場合、ICS1(F)はICS1(F)は、任意の関数G、 に対してICS1(G)より優れていないか、悪化しておらず、対称的にICS1(F)よりも良くないか悪いこともない。そうでない場合、

は - ICSI(F)は、変換の暗黙的な変換シーケンスを示すものと 生存機能F. 13.3.3.1のi番目のパラメータの種類にリストのi番目の引数は、暗黙的な変換を定義しますシーケンス と 13.3.3.2では、1つの暗黙の変換シーケンスが、より良い変換シーケンスまたは悪い変換シーケンスであることを、 よりも別の意味で定義しています。 場合はこれらの定義を考えると

は、実行可能な関数F1が、私は すべての引数のために別の実行可能な関数F2より 優れた機能となるように定義され、ICSI(F1)は、ICSI(F2)より悪い変換シーケンスではありません、その後、

....

このことから、我々は2つのオーバーロードの試合のどちらも、この要件に適合を見ることができます。1つの関数について、1つの変換シーケンスが良好であり、1つの変換が他の関数の対応する変換シーケンスよりも悪いため、実行可能な関数を決定することができない。

2番目のオーバーロードがconstではない場合、2番目のオーバーロードの変換シーケンスはどちらも変換する必要はありません(どちらも同じです)。これは他のオーバーロードより優れているため、あいまいさはありません。

3

2つの等しくランクの変換が可能です。

  • socket &socket const &

  • boost::system::error_codebool

手動で明確にすることができます:オーバーロードの解決のために

bool result = static_cast<socket const &>(s).non_blocking(ec); 

s.non_blocking(bool(ec)); 
+0

11秒で私を打つ! –

+0

@ R.MartinhoFernandes:私は手動でそれを曖昧化する方法を知っています。私が不思議に思うのは、getterがconstでないときにあいまいさがない理由です。 – bart

+0

@bart:その場合は、1つは他のものよりも良い*マッチです。 –