2015-02-02 3 views
4

나는 생각도 다음과 같은 코드에 대한 정당성을 찾을 수 없습니다 :C++ 11 std :: initializer_list 생성자 오버로드 규칙이 존재하는 이유는 무엇입니까?

std::vector<int> a{1,2} // calls (7) 
std::vector<int> a(1,2) // calls (2) 

// constructors from http://en.cppreference.com/w/cpp/container/vector/vector 
vector(std::initializer_list<T> init, 
     const Allocator& alloc = Allocator()); // (7) 

explicit vector(size_type count, 
       const T& value = T(), 
       const Allocator& alloc = Allocator()); // (2) 

다른 기능은 당신이 ((){})을 사용하는 건축 방법에 따라 호출이 나에게 매우 비뚤어진 것 같다된다 . 왜 std::initializer_list은 주어진 매개 변수와 완벽하게 일치하는 다른 기능보다 선호됩니까? 위의 2 위의 생성자가 C++ 11에서 더 이상 사용되지 않는 것으로 알고 있습니다. 아마도이 변경으로 인해서도 여전히 추론 할 수 없습니다. 이유가 인 경우입니다. 이 동작에 대해 볼 수있는 유일한 이점은 특정 값으로 컨테이너를 초기화 할 수 있으며 한 쌍의 중괄호 만 필요하다는 것입니다. std::vector<int> a{1,2}std::vector<int> a{{1,2}}. 하지만, 최소한 이것은 분명히 모호함과 과부하 해결에 대한 변화를 초과하지는 않습니다. Effective Modern C++의 Scott Meyers에 따르면 std::make_uniquestd::make_shared은 (오버로드 해결로 인해) 인터페이스의 일부로 구성에 사용되는 양식을 명시 적으로 명시해야합니다. 그건 나에게 어리 석다.

나는 뭔가를 놓치고 있음을 인정하지만, 나는 확실하지 않다. 무엇입니다. 예를 들어 방금 std::vector을 사용 했으므로이 기능에 대해 일반적으로 묻습니다.

+2

그것은 동등하게 이상한 느낄 것'경우 표준 : : 벡터 {1,2,3}','표준 : : 벡터 {1,2,3,4}','표준 :: a {1,2,3,4,5};'모두 이니셜 라이저 목록 생성자를 호출하지만'std :: vector a {1,2};는 사용하지 않습니다. –

+0

@ T.C. 그래서 나는'std :: initializer_list' 생성자에 우선권을주는 대신 std :: vector {{1,2,3}}'이어야한다고 주장 할 것입니다. – user1520427

+0

# 2가 더 이상 사용되지 않는다고 생각하는 이유도 모르겠습니다. 그렇지 않습니다. –

답변

3

이것은 C++ 11에서 매우 재미 있습니다. 그 이유는 괄호 안에 들어있는 인수에 타입이 없기 때문입니다. 그러나 이것에 대한 예외가 있으며, 그것이 존재하는 이유는 분명하지 않습니다 : "auto"변수가 중괄호 인수를 암시 적으로 이니셜 라이저 목록으로 처리 할 수있는 유일한 변수입니다. 그러나 자동 함수 유형이있는 경우이 이니셜 라이저 목록이 반환되지 않습니다.

그렇습니다. 초기화 프로그램 목록의 이점은 특정 값으로 컨테이너를 초기화 할 수 있다는 것입니다. 그리고 이것은 변화의 가치가있는 커다란 이점입니다!

이니셜 라이저 목록을 만들기 전에 각 값으로 std :: vector를 받거나 "빈"템플릿 클래스를 만드는 것과 같이 다른 값으로 컨테이너 내부의 각 클래스를 초기화 할 수있는 템플릿을 작성해야합니다. 나중에 각 값을 펀치.

또 다른 점은 초기화리스트는 C.에서 수입이 지칠대로 지친 <cstdarg>을 사용하는 것보다 안전한 방법으로 C++에 대한 가변 기능을 만들 수

는 조합 놀고 싶어 (가변 인자 템플릿 불구하고이에 더 잘 할)입니다 작은?

#include <iostream> 
#include <vector> 
#include <typeinfo> 

using namespace std; 


vector<int> func (const vector<int> &a) { //works 
//auto func (const vector<int> &a) -> vector<int> { //works 
//auto func (const vector<int> &a) { //don't even compile, "returns a initializer list" error 
    for (int i: a) { 
     cout << "My " << i << endl; 
    } 

    return {20 , 30}; 
} 

int main() 
{ 
    //play with anonymous functions 
    auto y = [ ](vector<int> e) { return e; }; //works 
    vector<int> x = y({20, 30}); 
    //auto y = [ ](){ return {20, 30}; }; //don't even compile, "returns a initializer list" error 
    //vector<int> x = y(); 

    //play with initialization 
    //vector<int> x = {2,2,20,30}; //works 
    //vector<int> x{2,2,20,30}; //works 
    //auto x = vector<int>{2,2,20,30}; //works 
    //Bellow, a common mistake of people initializing a int to a auto, like auto x = { 1 } 
    //auto x = {2,2,20,30}; //wrong, but compiles, its a initializer list 
    //auto x{2,2,20,30}; //wrong, but compiles, its a initializer list 

    //Play with return types 
    //vector<int> x = func(vector<int>(2,2)); //works only with vector<int> and auto with trailing type 
    //vector<int> x(func(vector<int>(2,2))); //works only with vector<int> and auto with trailing type 
    //vector<int> x{func(vector<int>(2,2))}; //works only with vector<int> and auto with trailing type 
    //auto x = func(vector<int>(2,2)); //works only with vector<int> and auto with trailing type 
    //auto x(func(vector<int>(2,2))); //works only with vector<int> and auto with trailing type 

    cout << typeid(x).name() << endl; 
    for (int i: x) { 
     cout << "My " << i << endl; 
    } 

    return 0; 
} 
+1

이것은 흥미 롭습니다. 그리고 왜 우리가이 행동으로 끝나는지를 설명하는 것으로 간다 (braced 인수에 타입이 없기 때문에). 필자는 표준의위원회가이 문제를 인식하지 못하고 과부하 해결과는 다른'std :: initializer_list'를 처리하는 대신에 "이중 중괄호"해결책을 찾아야한다고 생각합니다. 나는 왜 그들이 의도적으로 *이 행동을 원할지 모르겠다. 통일 된 초기화는 매우 우아 할 수있었습니다. – user1520427

관련 문제