暗黙変換が起こりません
-
28-09-2019 - |
質問
最後の質問を聞いたもの見しようとした場合に理解別のものです---ることも理解できない私の日とします。
これは非常に長い質問の声が少なくとも私はこの問いかに役立つ多くの人となりました。
をコードしているのは以下:
template <typename T> class V;
template <typename T> class S;
template <typename T>
class V
{
public:
T x;
explicit V(const T & _x)
:x(_x){}
V(const S<T> & s)
:x(s.x){}
};
template <typename T>
class S
{
public:
T &x;
explicit S(V<T> & v)
:x(v.x)
{}
};
template <typename T>
V<T> operator+(const V<T> & a, const V<T> & b)
{
return V<T>(a.x + b.x);
}
int main()
{
V<float> a(1);
V<float> b(2);
S<float> c( b );
b = a + V<float>(c); // 1 -- compiles
b = a + c; // 2 -- fails
b = c; // 3 -- compiles
return 0;
}
表1-3仕事を完璧に表現2になコンパイル。
している場合は理解し正しくはどうなるのです:
式1
- c では暗黙的に変換され
const
による標準変換シーケンスで構成される一 資格の変換). V<float>(const S<T> & s)
と呼ばれ、時間的にconst V<float>
オブジェクトの発生(う t).すでにconst修飾ですので時間的な値です。- a に変換される定数と同様に c.
operator+(const V<float> & a, const V<float> & b)
と呼ばれ、時間のタイプconst V<float>
と呼ぶことができま q.- デフォルトの
V<float>::operator=(const & V<float>)
が呼び出されます。
今までOK。まったものの微妙な間違いさん、うことにより理解を暗黙的に鋳造きましては、なるべく深く...
式3
- c に変換され
V<float>
.そして、ユーザによって定義された変換シーケンス
1.1.最初の標準変換:S<float>
へconst S<float>
経由の資格に変換します。
1.2.ユーザー定義の変換:const S<float>
へV<float>
通V<float>(const S<T> & s)
コンストラクタです。
1.3次標準変換:V<float>
へconst V<float>
経由の資格に変換します。 - デフォルトの
V<float>::operator=(const & V<float>)
が呼び出されます。
式2?
私がわからないのはなぜ問題がありますので、第二の表現です。理由は、次のいない可能ですか?
- c に変換され
V<float>
.そして、ユーザによって定義された変換シーケンス
1.1.初期標準変換:S<float>
へconst S<float>
経由の資格に変換します。
1.2.ユーザー定義の変換:const S<float>
へV<float>
通V<float>(const S<T> & s)
コンストラクタです。
1.3倍となっております。最終基準の変換:V<float>
へconst V<float>
経由の資格に変換します。 - 手順2-6と同じである場合には表現の1.
にはC++の標準よりも'こんにちは!(粉を山にして真ん中を問題へのと13.3.3.1.2.3!'る国:
ユーザが定義された変換は、指定されたテンプレート変換機能の標準変換シーケンスがいて完全一致。
ができない場合の資格の変換が正確な試合ランク...
私はこんな...
でも持っているかどうか、回答はいただきありがとうございますの読書のここまでのまとめ:)
解決
としてEdric指摘の通り、変換する時のテンプレートの引数を控除.ここでは、二つのコンテキスト内のテンプレートパラメータで明らかにされたのかの型引数:
template<class T>
v<T> operator+(V<T> const&, V<T> const&);
~~~~~~~~~~~ ~~~~~~~~~~~~
がんを起動するにはこの関数はテンプレート V<float>
左側の右側となります。テンプレートの引数を控除結果、T=floatの左側だエラーの右側にありませんのTう V<T>
equals S<T>
.このとして認定テンプレートの引数を控除に失敗し、テンプレートは単に無視されます。
したい場合は許可の変換オペレーター+などをテンプレートを作成します。あのトリック:を定義できますので、インラインの友人のクラスのテンプレートV:
template<class T>
class V
{
public:
V();
V(S<T> const&); // <-- note: no explicit keyword here
friend V<T> operator+(V<T> const& lhs, V<T> const& rhs) {
...
}
};
このように、オペレーターはテンプレートです。なので、必要がないためのテンプレートの引数を控除し、呼び出しできます。のオペレーターであるこADL(引数依存性のルックアップ)が、左側です V<float>
.右側が適切に変換され V<float>
しています。
ることも可能で無効にするテンプレートの引数を控除特定の引数に使います。例えば:
template<class T>
struct id {typedef T type;};
template<class T>
T clip(
typename id<T>::type min,
T value,
typename id<T>::type max )
{
if (value<min) value=min;
if (value>max) value=max;
return value;
}
int main() {
double x = 3.14;
double y = clip(1,x,3); // works, T=double
}
ものの、最初と最後の引数はint、考慮されていない時のテンプレートの引数を控除した id<T>::type
はない*と呼ばれる演繹可能な文脈`.なので、Tは導出による第二引数には、T=ダブルの無矛盾をはらんでいます。
他のヒント
を考えた場合テンプレートマッチ、暗黙的に変換を使用しておりません。このため、以下の簡単な例:
template < typename T >
void foo( T t1, T t2 ) { /* do stuff */ }
int main( int argc, char ** argv ) {
foo( 1, 1.0 );
return 0;
}
のないコンパイルのもののいずれかの引数が暗黙的に変換され、その他のタイプ(int <->double).
でも、そのコンパイラを識別できないとの間の変換からV->SまたはS->Vらを追加する方法を見つけ出すことa+c表2.いとのコンパイラがスマートなワークショップ】ワックスコードの作成を進のための機能がコンパイラがなくなるだろう"先読み"では、混乱してそこで、このような曖昧性のものに変換する前に、'+'ります。
もちろん、追加した場合のコンパイルエラーが明確にされる問題です。