2011-08-01 5 views
24

가능한 중복 : 당신은 초기화 목록을 잘 성병 :: 배열을 구성 할 수 있습니다
How do I initialize a member array with an initializer_list?이니셜 라이저 목록을 사용하여 std :: array 객체를 생성하는 방법은 무엇입니까?

그러나

std::array<int, 3> a = {1, 2, 3}; // works fine 

, 나는 그것을 구성하려고 클래스의 데이터 멤버 또는 기본 개체로 std::initializer_list에서 작동하지 않습니다.

GCC 4.
#include <array> 
#include <initializer_list> 

template <typename T, std::size_t size, typename EnumT> 
struct enum_addressable_array : public std::array<T, size> 
{ 
    typedef std::array<T, size> base_t; 
    typedef typename base_t::reference reference; 
    typedef typename base_t::const_reference const_reference; 
    typedef typename base_t::size_type size_type; 

    enum_addressable_array(std::initializer_list<T> il) : base_t{il} {} 

    reference operator[](EnumT n) 
    { 
     return base_t::operator[](static_cast<size_type>(n)); 
    } 

    const_reference operator[](EnumT n) const 
    { 
     return base_t::operator[](static_cast<size_type>(n)); 
    } 
}; 

enum class E {a, b, c}; 
enum_addressable_array<char, 3, E> ea = {'a', 'b', 'c'}; 

오류 :

test.cpp: In constructor 'enum_addressable_array<T, size, EnumT>::enum_addressable_array(std::initializer_list<T>) [with T = char, unsigned int size = 3u, EnumT = E]': 
test.cpp:26:55: instantiated from here 
test.cpp:12:68: error: no matching function for call to 'std::array<char, 3u>::array(<brace-enclosed initializer list>)' 
test.cpp:12:68: note: candidates are: 
include/c++/4.6.1/array:60:12: note: std::array<char, 3u>::array() 
include/c++/4.6.1/array:60:12: note: candidate expects 0 arguments, 1 provided 
include/c++/4.6.1/array:60:12: note: constexpr std::array<char, 3u>::array(const std::array<char, 3u>&) 
include/c++/4.6.1/array:60:12: note: no known conversion for argument 1 from 'std::initializer_list<char>' to 'const std::array<char, 3u>&' 
include/c++/4.6.1/array:60:12: note: constexpr std::array<char, 3u>::array(std::array<char, 3u>&&) 
include/c++/4.6.1/array:60:12: note: no known conversion for argument 1 from 'std::initializer_list<char>' to 'std::array<char, 3u>&&' 

가 어떻게 같은, 내 래퍼 클래스가 초기화리스트로 초기화 할 수 있도록 작업을 얻을 수 있습니다 :

enum_addressable_array<char, 3, E> ea = {'a', 'b', 'c'}; 

답변

26

std::initializer_list<> (초기화리스트 생성자)를 소요하고 그 작동 할 수 있도록 클래스 '생성자에 std::initializer_list<>를 전달하는 의미 무엇인지에 대한 특별한 언어 지원이없는 생성자가 없습니다. 그래서 그것은 실패합니다. 이 작업을 위해

, 파생 클래스가 전달할 모든 요소를 ​​잡을 필요가 생성자 템플릿 :

template<typename ...E> 
enum_addressable_array(E&&...e) : base_t{{std::forward<E>(e)...}} {} 

참고 중괄호 생략 (처럼 중괄호를 생략하기 때문에이 경우 {{...}}이 필요하여 케이스)가 그 장소에서 작동하지 않습니다. 이것은 형식이 T t = { ... } 인 선언에서만 허용됩니다. std::array<>은 원시 배열을 포함하는 구조체로 이루어져 있기 때문에 두 단계의 중괄호가 필요합니다. 불행히도, 정확한 집계 구조는 std::array<>으로 지정되지 않았으므로 대부분의 구현에서 작동하기를 바랍니다.

+4

Clang은 입력이 'E && ... e'이어야한다고 불평합니다. (그리고 때로는 g ++이 사람을 죽이라고 알려줍니다.) –

+1

복사 생성자 등을 덮어 쓰지 않습니까? 'template (std :: decl (...)}}>> enum_addressable_array (E && ... e) : base_t {{std :: forward alfC

+1

@alfC 템플릿은 암시 적으로 생성 된 특수 멤버 함수보다 더 정확하게 일치하지 않습니다. 정확하게 일치하는 템플릿이므로 (암시 적으로도 "enum_addressable_array &'와 같은 것을 넘겨 주면 더 좋은 결과를 얻을 수있다. (따라서 과부하 해결을 선호한다.) –

10

std::array에는 std::initializer_list을 사용하는 생성자가 없습니다. 이니셜 라이저 목록이 배열의 고정 크기보다 클 수 있기 때문에 좋은 방법입니다.

이니셜 라이저 목록이 배열 크기보다 크지 않은지 테스트 한 다음 이니셜 라이저 목록의 요소를 elems 구성원 인 std::arraystd::copy으로 복사하여 초기화 할 수 있습니다.

23

std::array은 집계가 포함 된 구조이므로 (집계 자체가 아니고 std::initializer_list을 사용하는 생성자가 없음) 두 배를 사용하여 이니셜 라이저 목록으로 구조 내부의 집계를 초기화 할 수 있습니다 -braces 구문과 같이이 단순히 std::array의 공개적으로 액세스 할 배열 구성원을 초기화하기 위해 C++ 초기화리스트를 사용하고 있습니다 ...이 std::initializer_list를 사용하지 않는 것을

std::array<int, 4> my_array = {{1, 2, 3, 4}}; 

참고. std::array<>

관련 문제