2014-10-19 3 views
3

함수를 N 개의 인수로 취할 때 사용할 수있는 것은? N은 프로그래밍 타임에 알 수 없지만 컴파일 타임에 고정됩니다 (실제로 템플릿 매개 변수입니다.)?N 개의 인수를 취하여 N 개의 값을 반환하는 고성능 솔루션

해당 기능은 성능에 중요한 경로에있는 액세스 기능이므로 가능한 최소한의 오버 헤드를 찾고 있습니다.

무엇이 가장 먼저 들릴지는 std::initializer_list이지만 값이 싸지 만 내가 말했듯이 작성하고 복사하는 것은 여전히 ​​불필요한 개체입니다. 더구나, initializer_list::begin[i] (나는 신경 쓰지 않는 또 다른 객체입니다)을 사용하여 요소에 액세스하는 펑키 한 방법이 있으며 N에 대한 인수의 수를 정확하게 제한하지 않지만 사소한 불만입니다.

둘째, 템플릿 매개 변수 팩이 있습니다. 그 후보가 유력한 후보가 될 수 있을까요? N 값에 액세스하려면 재귀를 사용해야합니다.

나는이 의사 코드에서 보여 주려고을 목표로하고있어 무엇 :

template<int dim, class T> class linear_searchspace { 

    template<T...args> operator() (args) { 
     return std::tie(some_kinda_structure[args[0]], some_kinda_structure[args[1]], some_kinda_structure[args[3]]); 
    } 

}; 

Hoow 내가 actualy 일하는 것이 재귀 형태를 가지고 있을까?

CLARIFICATION : 은 좌표로 간주됩니다. 각 좌표는 차원의 값 인덱스입니다. N 좌표가 전달되면 N 값이 리턴됩니다. 동시에 N 개의 벡터에 액세스하는 것과 같습니다. 인수의 인덱스에 해당하는 오프셋의 인덱스가있는 배열이 저장되므로 인수의 인덱스에 따라 각 인수에 오프셋을 추가하고 싶습니다. 계산은 단순한 산술 일 것입니다.

그리고 적절한 반환 유형은 무엇입니까? 이 구조체는 대부분 숫자 값, 튜플을 가질 것입니다. std::tuple이 내가 할 수있는 최선인가, 아니면 더 뛰어난 공연을 만드는 것이 가능한가?

인수와 관련해서는 매크로도 포함됩니다. 나는 몇 년 동안 당신이 생각해 낸 트릭을 듣게되어 매우 기쁩니다.

+1

'arg s'. –

+0

함수에서 반환 할 대상이 무엇인지 명확하지 않은 것은 무엇입니까? 어쩌면 벡터가 괜찮습니까? initializer_list는 친구입니다 – Ation

+0

C++ 11 또는 C++ 14? – Columbo

답변

2
double data[]={1,2,3,4,5,6,7,8}; 
double& toy_map(int x){return data[x];} 

template<class...Ts> 
auto example(Ts&&...ts) 
-> decltype(std::tie(toy_map(std::forward<Ts>(ts))...)) 
{ 
    static_assert(sizeof...(Ts)==5, "wrong parameter count"); 
    return std::tie(toy_map(std::forward<Ts>(ts))...); 
} 

toy_map의 순서는 지정되지 않았습니다.

SFINAE가 필요하지 않은 경우 C++ 14에서 decltype 행을 제거하십시오.

5N으로 바꾸십시오.

과부하가 완벽하기를 원한다면 SFINAE에 N 수표를 써야하지만 보통 과잉입니다.

+0

'std :: tie' is is 아마도 올바른 기능을 사용할 수 없습니다. –

+0

@ t.c. 예. 만든 장난감지도가 덜 어리석은 배열을 사용합니다. – Yakk

1

함수 매개 변수가 모두 동일한 유형이면 벡터로 전달할 수 있습니다. 모든 데이터를 벡터에 배치 한 다음 벡터를 함수에 전달합니다.

class Coordinate; 

std::vector<Coordinate> my_function(const std::vector<Coordinate>& data) 
{ 
    const unsigned int items_in_data = data.size(); 
    //... 
    return data; 
} 

벡터는 동적이며 벡터 안에 얼마나 많은 항목이 있는지 알 수 있습니다.

규칙에 따르면 함수에 많은 인수가 필요한 경우 인수를 구조체 나 컨테이너에 넣고 구조체 나 컨테이너를 전달합니다.

+2

단점 : 모든 통화시 할당. – Yakk

+1

@Yakk : 요소 수가 용량을 초과하는 경우에만 할당. 벡터 및 초기 크기로 만들 수 있습니다. –

4
template <std::size_t DIM, typename T> 
class linear_searchspace 
{ 
public: 
    template <typename... Args> 
    inline constexpr auto operator()(Args... args) const 
     noexcept(noexcept(T{std::declval<T>()})) 
     -> std::tuple<decltype((void)args, T{std::declval<T>()})...> 
    { 
     static_assert(sizeof...(Args) == DIM, "wrong number of indices!"); 
     using Tuple = std::tuple<decltype((void)args, T{std::declval<T>()})...>; 
     return get<Tuple>(make_index_sequence<sizeof...(Args)>{}, args...); 
    } 

private: 
    template <typename Tuple, typename... Args, std::size_t... Is> 
    inline constexpr Tuple get(index_sequence<Is...>, Args... args) const 
     noexcept(noexcept(T{std::declval<T>()})) 
    { 
     return Tuple((some_kinda_structure[args] + Is)...); 
     //          ^^^^ 
     // some calculation for each element based on index (here simple addition) 
    } 

    T some_kinda_structure[DIM]; // implementation defined 
}; 

전체 동작은 컴파일시 평가되기 때문에, 하나 constexpr 개체 최고의 성능을 얻는 상기 용액

DEMO

(index_sequence 구현 데모이다) 시간 :

int main() 
{ 
    constexpr linear_searchspace<5, int> lsp{}; 

    // evaluated at compile-time 
    constexpr auto t = lsp(0, 1, 2, 3, 4); 
    static_assert(std::get<1>(t) == 1, "!"); 

    // evaluated at run-time 
    auto t2 = lsp(4, 3, 2, 1, 0); 
    assert(std::get<3>(t2) == 3); 
} 
+0

고마워요. 이제 저는 조금 더 이해합니다 :-) – TeaOverflow

관련 문제