2016-12-03 5 views
2

KoenigによるAccelerated C++のコンテナの中央値を計算する次のC++コードがあります。C++:ソート関数での完全修飾名の使用 - 不整合な振る舞い

median.h

#ifndef GUARD_median_h 
#define GUARD_median_h 

#include <stdexcept> 
#include <algorithm> 
#include <cstddef> 

template<class T, class Iterator> 
T median (Iterator begin, Iterator end) 
{ 
    size_t size = end - begin; 
    if (size == 0) 
     throw std::domain_error("median of an empty vector"); 

    sort(begin, end); 

    size_t mid = size/2; 

    return size%2 == 0 ? (begin[mid] + begin[mid-1])/2 : begin[mid]; 
} 
#endif 

median_test.cpp

#include <vector> 
#include <iostream> 
#include "median.h" 

using std::vector; using std::cin; 
using std::cout; using std::endl; 

int main() 
{ 
    vector<double> myVec; 

    cout << "Please enter integers: "; 

    double val; 
    while (cin >> val) { 
     myVec.push_back(val); 
    } 

    cout << "The median is: " << median<double>(myVec.begin(), myVec.end()) << endl; 

    return 0; 
} 

このコードはコンパイルし、うまく動作します。私は配列ではなく、そのようなベクターを用いて中央値の機能をテストするために若干の修正を加えた場合でも...

median_test_array.cpp

#include <iostream> 
#include "median.h" 

using std::cin; 
using std::cout; using std::endl; 

int main() 
{ 
    double myVec[1000]; 

    cout << "Please enter integers: "; 

    double val; 
    size_t i = 0; 
    while (cin >> val) { 
     myVec[i++] = val; 
    } 

    cout << "The median is: " << median<double>(myVec, myVec+i) << endl; 

    return 0; 
} 

は、私は以下のコンパイルエラーを取得:

| => g++-6 -I. median_test_array.cpp 
In file included from median_test_array.cpp:2:0: 
median.h: In instantiation of 'T median(Iterator, Iterator) [with T = double; Iterator = double*]': 
median_test_array.cpp:19:60: required from here 
median.h:15:9: error: 'sort' was not declared in this scope 
    sort(begin, end); 
    ~~~~^~~~~~~~~~~~ 
median.h:15:9: note: suggested alternative: 
In file included from /usr/local/Cellar/gcc/6.2.0/include/c++/6.2.0/algorithm:62:0, 
       from median.h:5, 
       from median_test_array.cpp:2: 
/usr/local/Cellar/gcc/6.2.0/include/c++/6.2.0/bits/stl_algo.h:4727:5: note: 'std::sort' 
    sort(_RandomAccessIterator __first, _RandomAccessIterator __last, 
    ^~~~ 

このエラーは、ソート(std :: sort)の完全修飾名を指定すると消えますが、なぜこのインスタンスでは完全修飾名が必要ですが、ベクターの例では必要ではないかということです。

+1

http://stackoverflow.com/questions/8111677/what-is-argument-dependent-lookup-aka-adl-or-koenig-lookup – Brian

答えて

1

ADLです。あなたの第一のサンプルコードについては

が、それは実装が名前空間std内部クラスとしてstd::vector::iteratorを宣言しているようですし、ADLが有効になり、std::sortはタイプstd::vector::iteratorの引数を持つ呼び出しのために発見されました。

2番目のコードサンプルでは、​​sortに渡された引数はちょうどdouble*であり、ADLはもう有効ではなく、sortという名前は見つかりません。

このような動作は保証されません。標準ではstd::vector::iteratorの実装場所を指定していないため、クラスである必要はないため、修飾子std::を指定するか、using std::sort;と一緒に使用する方がよいでしょう。

2

最初のコードは、いわゆる引数依存ルックアップのためにコンパイルされました。 std::vector<double>::iteratorがネームスペースstdに属しているので、このネームスペースでは関数sortも検索されました。

ポインタを使用する場合、ADLはありません。したがって、コンパイラは、sortという名前の宣言を見つけることができません。

修飾名std::sortを使用してください。

関連する問題