2016-08-26 5 views
3

it was not standards-compliant을 발견 할 때까지 부분적으로 특수화 된 템플릿 코드를 VS ​​2015에서 중첩 시켰습니다. 나는 이전의 문제와 심지어 that one을 극복하기 위해 코드를 왜곡하고 지금은 단단한 벽에 부딪쳤다.템플릿 매개 변수 팩의 내용으로 배열을 채우는 방법은 무엇입니까?

variadic 템플릿과 부분 특수화를 사용하여 고정 된 매개 변수 집합이 주어진 컴파일 타임에 배열을 채우고 싶습니다.

내가 달성하고자하는 내용은 this answer과 유사하지만 작동하도록 관리하지 못했습니다. (버전 5.3.0)

#include <cstdlib> 

template <typename T, std::size_t Size> 
struct Array; 

template <typename T, std::size_t Size, std::size_t Iteration, typename ...Args> 
struct ArrayFiller { 
    inline 
    static void fill(Array<T, Size>& a, const Args&... args) { 
     ArrayFiller<T, Size, Iteration, Args...>::fill_recursive(a, args...); 
    } 

    inline 
    static void fill_recursive(Array<T, Size>& a, const T& i, const Args&... args) { 
     a.data[Size - Iteration - 1] = i; 
     ArrayFiller<T, Size, Iteration - 1>::fill_recursive(a, args...); 
    } 
}; 

template <typename T, std::size_t Size> 
struct ArrayFiller<T, Size, 0> { 
    inline 
    static void fill_recursive(Array<T, Size>& a, const T& i) { 
     a.data[Size - 1] = i; 
    } 
}; 

template <typename T, std::size_t Size> 
struct Array { 
    T data[Size]; 

    template <typename ...Args> 
    Array(const Args&... args) { 
     ArrayFiller<T, Size, Size - 1, Args...>::fill(*this, args...); 
    } 
}; 

int main() { 
    Array<int, 2> c(42, -18); 
    return 0; 
} 

... 그 g++ -std=c++14 -pedantic -Wall -Wextra 출력의 시작 :

다음 프로그램을 고려

main.cpp: In instantiation of ‘static void ArrayFiller<T, Size, Iteration, Args>::fill(Array<T, Size>&, const Args& ...) [with T = int; long unsigned int Size = 2ul; long unsigned int Iteration = 1ul; Args = {int, int}]’: 
main.cpp:34:54: required from ‘Array<T, Size>::Array(const Args& ...) [with Args = {int, int}; T = int; long unsigned int Size = 2ul]’ 
main.cpp:39:28: required from here 
main.cpp:10:65: error: no matching function for call to ‘ArrayFiller<int, 2ul, 1ul, int, int>::fill_recursive(Array<int, 2ul>&, const int&, const int&)’ 
     ArrayFiller<T, Size, Iteration, Args...>::fill_recursive(a, args...); 
                   ^
main.cpp:14:17: note: candidate: static void ArrayFiller<T, Size, Iteration, Args>::fill_recursive(Array<T, Size>&, const T&, const Args& ...) [with T = int; long unsigned int Size = 2ul; long unsigned int Iteration = 1ul; Args = {int, int}] 
    static void fill_recursive(Array<T, Size>& a, const T& i, const Args&... args) { 
       ^
main.cpp:14:17: note: candidate expects 4 arguments, 3 provided 

기본적으로 컴파일러는 어떤이는 것을 불평하지 왜냐하면 매개 변수 팩이 너무 빨리 또는 너무 늦게 내 논리에서 확장된다는 것을 이해하기 때문입니다. 재귀 호출의 const T& i 인수가 확장을 엉망으로 만듭니다.

어떻게 수정하겠습니까?

대체/더 나은/클리너 솔루션에도 관심이 있습니다.

+2

이니셜 라이저 목록이있는 constexpr 생성자가 수행 할 때 왜 가변적 템플릿이 필요합니까? – SergeyA

+0

그래,이 구문을 정확히 지원하는'std :: array'를 왜 사용하지 않았는지 모르겠다. 이것은 값을 생성하는 것을 의미하는 배열을 "채우지"않는다. 그것은 단지 제공된 값으로부터 초기화하는 것입니다. 그리고 C++ 표준 라이브러리가 필요로하는 휠을 이미 제공 한 경우에는 대개 스스로 다시 작성하려고하는 것이 좋습니다. –

+0

@ SergeyA : 정교하게 주시겠습니까? 비토리오의 대답은 무엇입니까? 미안하지만 다른 도구와 마찬가지로 C++에 익숙하지 않습니다. – dummydev

답변

8

사용 사례에서 허용되는 템플릿 재귀를 기반으로하지 않는 솔루션입니까? wandbox link

template <typename T, std::size_t Size> 
struct Array { 
    T data[Size]; 

    template <typename ...Args> 
    constexpr Array(const Args&... args) : data{args...} { 

    } 
}; 

int main() { 
    Array<int, 2> c(42, -18); 
    assert(c.data[0] == 42); 
    assert(c.data[1] == -18); 

    constexpr Array<int, 2> cc(42, -18); 
    static_assert(cc.data[0] == 42); 
    static_assert(cc.data[1] == -18); 
} 
+0

비토리오에게 감사드립니다, 이것은 눈을 뜨게 해주었습니다. 필자는 필자의 필요에 맞추기 위해'* this = Array (args ...);를하는 공용 설정기를 추가했다. – dummydev

관련 문제