2016-06-06 2 views
0

매개 변수 팩 확장 중에 각 매개 변수에 대한 카운터를 증가시키고 싶습니다. 의 Args의 순서가 유지되는 동안C++ 11 : 매개 변수 팩 확장 카운터

template<class ... Args> 
    void doSomething(Args ... _args) 
    { 
     std::size_t counter = 0; 
     bar(doSomethingWithOneArg(_args, counter++)...); 
    } 

이 코드의 문제는, 함수 매개 변수가 평가되는 순서가 정의되어 있지 않은 것을 : 는 여기에 내가 무엇을 달성하고자하는 일부 의사 코드 즉 clang에서 카운터 표현식이 평가되는 순서는 Args의 순서와 같지만 gcc의 순서는 바뀝니다. 이것을 달성하기위한 이식 가능한 표준 방법은 무엇입니까?

감사합니다.

+1

평소 의견 : 왜 이것을 원하니? – GManNickG

+1

나는이 질문에 내가 당신에게 도움이 될지도 모른다고 생각한다. http://stackoverflow.com/a/12006450/63791 – Alex

+0

@GManNickG 현재 일부 루아 바인딩 코드를 작성 중이고 루아 스택 인덱스를 생성하고 싶다. 파리. – moka

답변

4

당신은 도우미 기능을 추가 할 수 있습니다

template <typename ...Args> 
void doSomething(Args &&... args) 
{ 
    doSomethingImpl(std::make_index_sequence<sizeof...(Args)>(), 
        std::forward<Args>(args)...); 
} 

template <typename ...Args, std::size_t ...N> 
void doSomethingImpl(std::index_sequence<N...>, Args &&... args) 
{ 
    bar(oneCommand(std::forward<Args>(args), N)...); 
} 
+1

[데모] (https://ideone.com/2JqqLb) –

+0

위대한,'std :: make_index_sequence'에 대해 몰랐다. 데모를 위해, 내가 뭘 찾고 있었는지 고마워! – moka

+0

답변으로 받아 들였습니다. 내가 변경 한 유일한 방법은 C++ 11에서 사용할 수 없으므로 index_sequence의 자체 구현을 사용하는 것입니다. – moka

1

당신은 doSomething에 대한 인수의 순서 당신이 초기화에 인수를 확장 할 수 있습니다에 부합하는 것으로 평가의 순서를 원하는 경우 :

template <typename ...Args, std::size_t ...N> 
void doSomethingImpl(std::index_sequence<N...>, 
    std::tuple<Args...> && args) 
{ 
    using std::get; 
    int t_[] = { 0, (static_cast<void>(oneCommand(
    get<N>(std::forward<decltype(args)>(args)), N)), 0)... }; 
    static_cast<void>(t_); // "use" t_ to silence warnings 
} 

template <typename ...Args> 
void doSomething(Args &&... args) 
{ 
    doSomethingImpl(std::make_index_sequence<sizeof...(Args)>(), 
    std::forward_as_tuple(std::forward<Args>(args)...)); 
} 
+0

C 스타일 캐스팅이 왜 필요한가요? :-( –

+0

@KerrekSB : C 스타일 캐스팅 표기법을 사용하여 버려진 표현식/반환 값을 void로 캐스팅하는 최하위 버릇입니다. – Pixelchemist

1

당신은 기능을 시퀀스 쉼표 연산자와 함께리스트 initializatio을 활용할 수있는 것은 호출

template<class T> 
void doSomethingWithOneArg(const T&, std::size_t counter) 
{ 
    std::cout << counter << ": " << typeid(T).name() << '\n'; 
} 

template<class ... Args> 
void doSomething(Args ... args) 
{ 
    std::size_t counter = 0; 
    std::initializer_list<int>{ (doSomethingWithOneArg(args, counter++), 0) ... }; 
} 

int main() { 
    doSomething(char(0), int(0), long(0)); 
} 
,

8.5.4 목록 초기화 (N4296)를 보강-초기화 목록의 초기화 목록 내에서

, 팩 확장의 결과 어떤을 포함하여 초기화-조항, (14.5.3)은 나타나는 순서대로 평가됩니다. 즉, 모든 값 계산 및 부작용이 주어진 initializer-clause와 관련된 모든 값 계산 및 부작용이 후속되는 이니셜 라이저 절과 연관된 이니셜 라이저 목록의 쉼표로 구분 된 목록 에 있습니다.

관련 문제