2017-11-04 23 views
0

私は関数テンプレートを使うことを学んでいます。引数型を参照として宣言すると、プログラムが動作することがわかります。しかし、引数の型が参照でない場合はエラーになります。例:C++関数テンプレート:引数の型と戻り値の型に&を使用する必要がありますか?

次のコードは正しい結果を出力し、エラーなしで動作します。私はすべての「&」のコードを削除する場合は、次のよう

#include <iostream> 
using namespace std; 

template <typename T> 
T & max (T & a, T & b){ 
    return a>b?a:b; 
} 

int main(int argc, char const *argv[]) 
{ 
    cout << max(1,2) << endl; 
    return 0; 
} 

はしかし、すなわち、上記のプログラムを変更します。このコードは、次のエラーにつながる

#include <iostream> 
using namespace std; 

template <typename T> 
T max (T a, T b){ 
    return a>b?a:b; 
} 

int main(int argc, char const *argv[]) 
{ 
    cout << max(1,2) << endl; 
    return 0; 
} 

a.cpp: In function ‘int main(int, const char**)’: 
a.cpp:11:17: error: call of overloaded ‘max(int, int)’ is ambiguous 
    cout << max(1,2) << endl; 
       ^
a.cpp:5:4: note: candidate: T max(T, T) [with T = int] 
T max (T a, T b){ 
    ^~~ 
In file included from /usr/include/c++/7/bits/char_traits.h:39:0, 
       from /usr/include/c++/7/ios:40, 
       from /usr/include/c++/7/ostream:38, 
       from /usr/include/c++/7/iostream:39, 
       from a.cpp:1: 
/usr/include/c++/7/bits/stl_algobase.h:219:5: note: candidate: constexpr const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int] 
    max(const _Tp& __a, const _Tp& __b) 

なぜですか? 私を助けてくれてありがとう!

+3

コンパイラがわかります:最高のあなたの呼び出しが曖昧で、最大テンプレートは名前空間stdを使用して '使用しない理由はもう一つの理由は、std名前空間 –

+3

にありますので、私は推測;' – user0042

+0

最初の例は無効であり、あなたがあなたを使用していませんテンプレート。 –

答えて

2

stdネームスペースで同じ(または互換性のある)名前とパラメータタイプが定義されている関数(テンプレート)がすでにあります。

using namespace std; 

を削除するとstdとCOUTとENDLの接頭辞::

std::cout << max(1,2) << std::endl; 

そうしないと、std名前空間内のすべての名前を使用してグローバルな名前空間を汚染しています。

2

最初の例では、変更可能な左辺値の参照に適さないため、参照パラメータのバージョンは考慮されていません。また、助言を受けたusing namespace std;のおかげで、あなたはstdバージョンを代わりに使用しています。これはうまくいきます。 maxコードを最初のバージョンで削除しても問題はありません。これは、一度それらの参照が失格を引き起こしたと見なされないためです。

要するに、それは資格がないので、最初のバージョンは、あなたのmaxコードを考慮していないので、std::maxは(が資格ん)の代わりに使用されています。 2番目のバージョンでは、値引数を使用するコードとconst参照を使用するバージョンstd::maxの両方が修飾される可能性があるため、結果があいまいになります。

0

名前空間std(標準ヘッダー<algorithm>)の引数に受け入れるテンプレート付きmax()関数があります。標準では、その機能を#include <iostream>によって導入する必要はありませんが、それを禁止していません。あなたの標準コンパイラは<iostream>でそれを紹介しています。

usingディレクティブ(using namespace std)を使用すると、std::max()テンプレートはコード内で一致する関数の候補とみなされます。それはconst参照を受け入れ、非const参照を受け入れ、あなたの機能よりも一致があるため、あなたの最初のコードサンプルで

は、コールmax(1,2)std::max()にマッチしています。あなたが期待する出力を生成することが起こります。2番目のコードサンプルで

は、値渡し、コンパイラは、(値渡しまたはconst参照渡しstdでのmax()または1のどちらかを優先する理由を持っていない両方1等リテラルintを通過させるために等しく有効です2)。したがって、コンパイラはあいまいさについて不平を言う。

キャッチは:<iostream>は、std::max()を宣言する必要はなく、すべての実装が行うわけではないので、異なるコンパイラ(またはそれらの標準ライブラリ)でコードが違う場合があります。

usingディレクティブを削除すると、コード内に潜在的な使用方法std::max()が表示されなくなります。std::max()は、どちらのコードサンプルでも候補にはなりません。非const参照を使用してリテラル値を渡すことはできないため、最初のサンプルはコンパイルされません。 2番目はコンパイルし、期待する出力を生成します。この動作は、標準準拠のC++コンパイラ間で一貫しています(<iostream>などの標準ヘッダがstd::max()と宣言されているかどうかには影響しません)。

関連する問題