2014-01-14 3 views
0

일부 TMP 및 constexpr C++ 11 마법을 사용하여 컴파일 타임 배열로 작동 할 수있는 클래스를 작성하려고했습니다. 내가 달성하기 위해 노력하고 최종 목표는 기본적으로 임의의 TypeSize를 들어gcc 4.7.2 오류 variadic 템플릿

Array<Type, Size, X> array; 

Type array[Size] = {X, X, X, ..., X}; 

을 쓸 수있게되고 (단지 컴파일러의 재귀 깊이에 의해 제한). 의 Array 객체 자체가 유형 Helper<2>...의 멤버를 초기화 유형 Helper<1>의 멤버를 초기화 유형 Helper<0>의 멤버를 초기화 추가 :

template <typename T, size_t Size, T Value = T()> 
struct Array 
{ 
    template <size_t Count, T ... Elements> 
    struct Helper 
    { 
     constexpr Helper() {} 
     Helper<Count + 1, Value, Elements...> helper; 

     constexpr T const *get() const 
     {   
      return helper.get(); 
     } 
    }; 

    template <T ... Elements> 
    struct Helper<Size, Elements ...> 
    { 
     constexpr Helper() {} 
     T array[Size] {Elements...}; 

     constexpr T const * get() const 
     { 
      return array; 
     } 
    }; 

    constexpr Array(): 
     helper(), 
     array{helper.get()} 
    {} 

    Helper<0> helper; 
    T const *array; 

    constexpr operator T const *() 
    { 
     return array; 
    } 
}; 

이 발생하는 것입니다 : 이것은 내가 생각 해낸 것입니다 Helper<Size, ...>에 대한 특수한 템플리트가 인스턴스화 될 때까지 각 iteraton의 한 요소. 지금까지 variadic 팩은 정확히 Size 요소를 포함하며, 중괄호로 묶인 이니셜 라이저 목록에 사용되어 최종 Helper 객체에 포함 된 배열을 초기화 할 수 있습니다. 이것은 신비한 오류가 나오는 곳입니다 :

error: ‘Elements’ was not declared in this scope 

죄송합니다. 선언하지 않았습니까? 바로 템플릿 매개 변수입니다. 나는 아주 명백한 것을 간과하고 있는가?

+0

작동하지 않습니다 ... – Jarod42

+0

g ++ 4.8.1에서도 실패합니다. – Jarod42

답변

1

해결 방법으로 Helper을 템플릿 클래스 외부로 옮기는 것이 효과적입니다.

도움이 될 수 있습니다 다음은 MakeArrayHelper 더 큰 크기를 허용 (그래서 더 큰 크기에 대한 재귀 한계에 도달)을 Size/2 대신 Size - 1와 재귀로 다시 작성 될 수 있음을

namespace detail { 

template <typename T, T value, T ... Elements> 
struct ArrayHelper 
{ 
    constexpr ArrayHelper() {} 
    T array[sizeof...(Elements)] {Elements...}; 

    constexpr T const * get() const { return array; } 
}; 

template <std::size_t Size, typename T, T value, T ... Elements> 
struct MakeArrayHelper 
{ 
    typedef typename MakeArrayHelper<Size - 1, T, value, value, Elements...>::type type; 
}; 

template <typename T, T value, T ... Elements> 
struct MakeArrayHelper<0, T, value, Elements...> 
{ 
    typedef ArrayHelper<T, Elements...> type; 
}; 

} // namespace detail 

template <typename T, size_t Size, T Value = T()> 
struct Array 
{ 
    constexpr Array(): 
     helper(), 
     array{helper.get()} 
    {} 

    typename detail::MakeArrayHelper<Size, T, Value>::type helper; 
    T const *array; 

    constexpr operator T const *() const { return array; } 
}; 

참고.

+0

대단히 고마워! 내가 버그 보고서를 제출해야한다고 생각하니? – JorenHeit

+0

@JorenHeit : 아직 없는지 확인하십시오. 최소한의 코드로 예제를 최소화하십시오. 템플릿 구조체 S { 템플릿 구조체 내부 {int a {V}; }; }; ' – Jarod42

+0

완료 : [Bug 59809] (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59809) – JorenHeit

관련 문제