2016-12-08 1 views
1

일부 값 N (N은 코드의 일부가 아님)에 대해 N foo의 튜플을 반환하도록 쓰는 함수가 필요합니다.<array>없이 균일 한 유형의 튜플을 선언하는 방법은 무엇입니까?

C++ 14 인 경우 실제로 아무것도 선언하지 않고 반환 유형으로 auto을 사용하지만 C++ 11에서는 작동하지 않습니다. -> auto decltype을 사용하고 싶지 않습니다. 그 이유는 로트을 의미 할 것이기 때문에, 나는 std::tuple{foo, foo, foo, foo}라고 쓸 수 있습니다.

또 다른 대안은 리턴 유형이 std::array<foo, N> 인 것입니다. 이것은 아마도 효과가 있어야합니다. 내가 궁금해하는 점은, 실제로 내가 필요로하지 않는 기능을 가진 <array>을 모두 사용하지 않고 얻을 수 있는지 여부입니다.

+3

튜플은 일반적으로 * 다른 * 유형의 정렬 된 컬렉션을 원할 때 선택됩니다. 배열 은 N foos이며, 터미널 케이스가 1 대신 0 일 때 – Caleth

답변

-1

일반 기능으로는 불가능합니다.

함수의 반환 유형이 고정되어 있으며 변경할 수 없습니다. 서로 다른 # 유형의 튜플은 각각 다른 유형이므로 다른 튜플 유형을 반환하는 단일 함수를 가질 수 없습니다.

예 : tuple<int, int>는 발신자가 명시 적으로 함수 호출을하면서 기대 수익 튜플 유형을 지정하면이 함수 템플릿이 할 수있는, 그런 말로 미루어 보아, tuple<int,int,int>

에 비해 다른 유형 (make_shared이 방법을 구현)입니다. 튜플이 장황 할 때 유용성이 좋지 않다고 생각합니다.

std :: array (또는 std :: vector)를 사용하면 경로가 더 쉬울 수 있습니다.

4
#include <tuple> 
#include <utility> 
#include <iostream> 

namespace detail { 

// the concept of N Ts. This is a type generator. 
template<class T, std::size_t N> 
struct tuple_of_n 
{ 
    using rest_tuple = typename tuple_of_n<T, N-1>::type; 
    using type = decltype(std::tuple_cat(std::declval<std::tuple<T>>(), std::declval<rest_tuple>())); 
}; 

// terminal case where N is 0  
template<class T> 
struct tuple_of_n<T, 0> 
{ 
    using type = std::tuple<>; 
}; 
} 

// typedef turns the generator into a type 
template<class T, std::size_t N> 
    using tuple_of_n = typename detail::tuple_of_n<T, N>::type; 

int main() { 

    // test 
    using two_ints = tuple_of_n<int, 2>; 

    // proof of equivalency 
    two_ints is = std::make_tuple(2, 4); 

    std::cout << std::get<0>(is) << std::endl; 
    std::cout << std::get<1>(is) << std::endl; 

    return 0; 
} 
+0

을 사용하는 것이 훨씬 간단합니다. – jaggedSpire

+0

@jaggedSpire 그게 합리적이라고 생각합니다. 그것은 간단한 편집입니다. –

3

다음과 같이 볼 수 있었다 integer_sequence [integer_seq.h]의 외부 된 구현을 사용하여 C++ 14 비트를 스타일링은 C++ (11) 접근 방식 : 나는 갈거야

#include <tuple> 
#include <utility> 
#include <iostream> 
#include <initializer_list> 
#include "integer_seq.h" 

using namespace redi; 


template <class T, std::size_t N, class = make_index_sequence<N>> 
struct tuple_generator; 

template <std::size_t, class T> 
using typer = T; 

template <class T, std::size_t N, std::size_t... Is> 
struct tuple_generator<T, N, index_sequence<Is...>> { 
    using type = std::tuple<typer<Is, T>...>; 
}; 

int main() { 
    static_assert(std::is_same<tuple_generator<int, 3>::type, std::tuple<int, int, int>>::value, "!"); 
} 

[live demo]

+1

C++ 11에 사용할 수있는 공개 구현 색인 시퀀스를 포함해야합니다. GitHub에. – einpoklum

+0

맞아요. 아마도 코드가 훨씬 명확해질 것입니다. –

2

을 @Smeeheey의 대답에서 내가 물어 본 다른 질문에 대한 아이디어를 재활용하십시오. C++ parameter pack, constrained to have instances of a single type?

연결이 문제가되지 않았습니다. 실제로는

여러 번 반복되는 동일한 유형의 매개 변수 팩을 만들려면 어떻게해야합니까?

그리고 가장 간단한 대답은은, std::make_index_sequence 사용하고 팩 확장 :

#include <tuple> 
#include <utility> 

template <typename T, unsigned n> 
struct repeat_tuple { 
    template <unsigned> 
    struct blah { 
    using type = T; 
    }; 

    template <typename IS> 
    struct helper; 

    template <unsigned ... Is> 
    struct helper<std::integer_sequence<unsigned, Is...>> { 
    using type = std::tuple<typename blah<Is>::type...>; 
    }; 

    using type = typename helper<std::make_integer_sequence<unsigned, n>>::type; 
}; 

template <typename T, unsigned n> 
using repeat_tuple_t = typename repeat_tuple<T, n>::type; 

static_assert(std::is_same<repeat_tuple_t<int, 3>, std::tuple<int, int, int>>::value, ""); 

int main() {} 

이 궁극적으로 W.F.의 대답과 같은,하지만 어쩌면 조금 terser이다. 편집 : 그는 그의 대답에 C + + 14 특성을 backporting 것 같아요.

이 접근법은 tuple_cat 접근 방식과 달리 튜플 외의 다른 것들에도 적용됩니다.

실제로 여기 std::tuple 템플릿 템플릿 매개 변수가 될 수 있습니다 ...

: 악의적 눈 :

관련 문제