2009-05-15 30 views
23

最近の私の答えであるWhat other useful casts can be used in C++には、C++の変換についての私の理解に誤りがあることが示唆されています。ただ、次のコードを検討し、問題を明確にする:私の主張C++の暗黙的な変換

#include <string> 

struct A { 
    A(const std::string & s) {} 
}; 

void func(const A & a) { 
} 

int main() { 
    func("one");     // error 
    func(A("two"));   // ok 
    func(std::string("three")); // ok 
} 

を最初の関数呼び出しがエラーであるA.へのconstのchar *からの変換はありませんbecauuse、からの変換があるということでした文字列をAに変換しますが、これを使用すると複数の変換が行われます。私はこれが許されないと理解しています。これはg ++ 4.4.0 &コモコンパイラによって確認されたようです。コモーで、私は次のエラーを取得する:

"ComeauTest.c", line 11: error: no suitable constructor exists 
     to convert from "const char [4]" to "A" 
     func("one");     // error 

あなたは、好ましくは、C++標準を参照して、ここでもか、元の答えに、私は間違っているところ、指摘することができた場合は、そうしてください。

そして、C++標準からの答えのようだ:引用符を提供するためのアブヘイに

At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.

感謝。

+0

申し訳ありませんが、私はあなたの答えにコメントに間違っていた。私は "オーバーロードの解像度は、呼び出されるユーザー定義の変換を選択するために使用されます"と私は自分自身に言った、それはA(文字列const&)に解決し、 "1"を渡すが、 13.3.3.1.2は、「ユーザ定義の変換シーケンスは、最初の標準変換シーケンスの後に ユーザ定義変換(12.3)が続き、その後に2番目の標準変換シーケンスが続くことから構成されています。しかし、 "one" - > stringは標準の変換シーケンスではありませんが、別のユーザ定義の変換シーケンスが必要です! –

+0

ちょうど私の大理石を失っていない限り:-) –

+0

大きな質問!この議論は、 'std :: string'は言語の一部ではなく、それとの変換は「ユーザ定義」であることを意味します。少なくともそれは私の理解です。私が間違っていれば私を修正してください。質問がこれについてもっと明白であればいいだろう。 'std :: string'の正確な状態は、古いC++の手にとっては明快かもしれませんが、今世紀にこの言語に来た人にとってはそれほど簡単ではありません。 –

答えて

12

私はsharptoothからの答えは正確だと思います。 「変換」と題されたC++標準(SC22-N-4411.pdf)セクション12.3.4では、暗黙的なユーザー定義変換は1つしか許可されていないことが明らかです。

1 Type conversions of class objects can be specified by constructors and by conversion functions. These conversions are called user-defined conversions and are used for implicit type conversions (Clause 4), for initialization (8.5), and for explicit type conversions (5.4, 5.2.9).

2 User-defined conversions are applied only where they are unambiguous (10.2, 12.3.2). Conversions obey the access control rules (Clause 11). Access control is applied after ambiguity resolution (3.4).

3 [ Note: See 13.3 for a discussion of the use of conversions in function calls as well as examples below. —end note ]

4 At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.

+0

私は、特定のシナリオで暗黙的な変換を使用することを楽しむ理由を共有することを強く感じています。つまり、変数に関連する関数を実行するクラスに単純型の変数を結合する場合です。暗黙の変換に加えて、std :: stringがc_str()を提供するのと同じ方法で、値を返す関数をクラス内で提供します。その後、必要に応じて余分なクラス機能を持たせることができます。また、関連する機能を一緒に保ちながら、他の場所と比べて非常に軽量化することができます。 – moodboom

8

暗黙的にの変換が1つだけ可能です。

変換演算子とパラメータ化されたコンストラクタを組み合わせて1つの行の2つの変換を実行することがありますが、C4927 warning - 「不正な変換、複数のユーザー定義変換が暗黙的に適用されています」理由。

5

The C++ Programming Language(第四編。)(セクション18.4.3)は、「ユーザ定義」の部分は、一部がネイティブの間にある場合は、複数の暗黙の変換を許可することができるようにそれが聞こえる

only one level of user-defined implicit conversion is legal

ことと言いますタイプ。

+0

+1の引用フォームは、最新のed。 Stroustrupの本の – mloskot

9

すでに合意が成立しているようです:はい、あなたは正しいです。

しかし、この質問/回答はおそらくstackoverflowでのC++暗黙の変換の参照ポイントになるでしょう。私はテンプレート引数にルールを追加したいと思います。

テンプレート引数の控除に使用される引数には、暗黙の変換は許可されません。これはかなり明白に見えるかもしれませんが、それにもかかわらず微妙な奇妙さにつながる可能性があります。

ポイントのケース、のstd ::文字列追加オペレータ

std::string s; 
s += 67; // (1) 
s = s + 67; // (2) 

(1)コンパイルし、正常に動作し、operator+=はメンバ関数で、テンプレート文字パラメータは、すでにcharに(秒std::stringをインスタンス化することによって推定されます)。したがって、暗黙的な変換は許可されます(int - >char)。ASCIIでは、これはoperator+はフリー機能と、ここが控除に使用されているテンプレートの文字引数として宣言されているよう

(2)コンパイラエラーを与える「C」になります。

関連する問題