2015-01-19 5 views
4

생성 된 요소 목록을 임의로 만들려고합니다. 코드는 다음과 같습니다.std :: shuffle이 std :: list와 함께 컴파일되지 않습니다.

std::default_random_engine generator (10); 
std::list<int> list(10); 

int n = 0; 
std::generate(list.begin(), list.end(), [&]{ return n++; }); 
std::shuffle(list.begin(), list.end(), generator); 

컴파일되지 않습니다. 다음은 오류입니다.

/include/c++/v1/algorithm:3059:34: Invalid operands to binary expression ('std::__1::__list_iterator<int, void *>' and 'std::__1::__list_iterator<int, void *>') 
main.cpp:1:10: In file included from main.cpp:1: 

/include/c++/v1/random:1641:10: In file included from /bin/../include/c++/v1/random:1641: 

main.cpp:37:10: In instantiation of function template specialization 'std::__1::shuffle<std::__1::__list_iterator<int, void *>, std::__1::linear_congruential_engine<unsigned int, 48271, 0, 2147483647> &>' requested here 
/include/c++/v1/iterator:622:1: Candidate template ignored: could not match 'reverse_iterator' against '__list_iterator' 
/include/c++/v1/iterator:1017:1: Candidate template ignored: could not match 'move_iterator' against '__list_iterator' 
/include/c++/v1/iterator:1369:1: Candidate template ignored: could not match '__wrap_iter' against '__list_iterator' 
/include/c++/v1/string:486:11: Candidate template ignored: could not match 'fpos' against '__list_iterator' 

아무도 아이디어가 있습니까?

답변

8

std::shuffle에는 임의 액세스 반복기가 필요합니다. std::list은 이러한 정보를 제공하지 않습니다. std::vector과 같은 다른 컨테이너가 필요합니다.

std::list이 정말로 필요한 경우에는 전용 알고리즘으로 셔플을 구현해야 할 수도 있습니다. 하지만 먼저 정말로 필요한지 확인하십시오. 사람들은 종종 std::vector이 필요할 때 std::list이 필요할 것이라고 생각합니다.

12

std::list은 요소에 임의 액세스를 제공하지 않으므로 std::shuffle()에 필요합니다. 이 std::shuffle()의 서명은 사양 (C++ 표준의 제 25.3.12)처럼 보이는 방법입니다

template<class RandomAccessIterator, class UniformRandomNumberGenerator> 
void shuffle(RandomAccessIterator first, 
      RandomAccessIterator last, 
      UniformRandomNumberGenerator&& g); 

당신은 대신 std::vector 사용을 고려할 수있는 경우 - 그건 그렇고, 당신은에 권장되는, C++ 표준 자체에서 기본 순차 컨테이너로 사용합니다.

int main() 
{ 
    std::default_random_engine generator(10); 
    std::vector<int> v(10); 

    std::iota(begin(v), end(v), 0); 
    std::shuffle(begin(v), end(v), generator); 

    for (auto x : v) { std::cout << x; } 
} 

std::iota() 알고리즘은 std::generate의 특정 사용에 단지 간단한 대안입니다 : 예 (live demo on Coliru)로

.

+0

'iota' 호출은 ADL을 통해'std :: iota'를 가져 오는 것이 보장되지 않습니다. –

+0

@ T.C .: 맞습니다. 벡터 반복자는 포인터 일 수 있습니다. 나는 그 전화를 자격을 얻는 편이 낫다. –

3

[algorithms.general] shuffle의/2 선언 :

template<class RandomAccessIterator, class UniformRandomNumberGenerator> 
void shuffle(RandomAccessIterator first, RandomAccessIterator last, 
       UniformRandomNumberGenerator&& rand); 

[...]

알고리즘의 템플릿 파라미터 RandomAccessIterator [...] 실제 템플릿 인수이면 (24.2.7)의 요구 사항을 만족해야한다.

분명히 std::list은 양방향 반복기만을 제공합니다. 대신 무작위 액세스 반복자를 제공하는 컨테이너를 사용해보십시오.