2016-12-21 13 views
0

두 가지 (다른 유형)를 반환하는 API 함수가있는 작은 라이브러리를 작성하고 있습니다. 차라리 구조체를 선언하지는 않을 것입니다. 그래서 나는 std::pair<foo, bat>을 돌려 줄 것을 생각하고있다. 그러나 - 아마 이러한 현대 시대에 나는 대신 std::tuple<foo, bar>을 돌려 주어야 할까?API 디자인에서 한 쌍에 대해 길이 2 std :: tuple을 언제 선호해야합니까?

더 일반적으로, 튜플이 쌍을 넘어서는 경우 언제 더 쌍을 더 적절한 구조로 만들어야합니까?

+13

근년에 적절하게 이름 지어진 멤버가있는 구조체는 멤버가있는'std :: tuple'뿐만 아니라'first'와'second' 멤버가있는'std :: pair '보다 훨씬 뛰어납니다 '<0>()'및'<1>()'을 얻습니다. –

+0

두 값이 관련되어 있으면 전 직원 ID, 직원 이름 다음 구조체 내 의견에 더 좋을 것입니다. – ArmenB

+0

API 디자인의 유스 케이스에 대한 예를 들려 줄 수 있습니까? –

답변

6

구조체를 선언해야합니다.

get<0>(x)get<1>(x), 또는 사후 C++ (11)의 get<Foo>(x)get<Bar>(x), x.foo 또는 x.bar 이하의 의미 및/또는 관용적이다.

tuple은 순서에 의해 식별되는 형식이 일 정치 않은 항목에 가장 적합합니다.

pair은 C++ 11 이전에 작성된 tuple입니다.

모두 pairtuple (그리고 array 우리가에있는 동안은), 튜플과 같은 점에서 그들은 std::tuple_sizeget<N>을 지원합니다.

std 라이브러리에서 많은 유형이 올바르게 명명 된 필드가있는 구조 대신 pair을 사용한다는 오류가 발생했습니다. 즉, mapstruct KV{ Key key; Value value; }을 사용하면 더 좋았을 것입니다.

이제 일반 쌍으로 KV에 대한 메타 프로그래밍 지원도 좋을 것입니다. 따라서 tuple_sizeget<0> 등입니다. 그러나 이름이 지정된 필드를 버리는 것은 일반적으로 좋지 않습니다. 이름에는 힘이 있습니다.

C++ 17의 경우 간단하게 struct은 "tuple-like"가 아니더라도 구조화 된 바인딩으로 작업하기 시작합니다.

신원이 균일하지 않은 순서로 결정되는 항목이있는 경우 이동 방법은 tuple입니다. pair은 거의 레거시 유형입니다. pair에는 몇 가지 장점이 있지만 tuple을 암시 적으로 초기화하는 것처럼 개선하기 위해 tuple을 계속 개선 할 수 있습니다 (tuple 암시 적 초기화).

0

하지만 최근에는 아마도 std::tuple<foo, bar>을 반환하는 것이 좋습니다.

더 일반적으로 튜플이 한 쌍 이상일 때 일 때 언제 더 적절한 구조로 페어링해야합니까?

글쎄, 당신이 오히려 std::tuplestd::pair (A)보다 걸릴 것으로 예상 (메타) 알고리즘 작업 할 경우에 유용 할 수 있습니다.

마지막으로 실제 사용 사례에 따라 달라 지므로 모르게 대답 할 수 없습니다.

본질적으로 (문맥에서 의미 상으로 관련이있는) 한 쌍의 유형과 일치하는 상황이 발생하면 std::pair을 사용하여 API에서 이러한 의미를 반영하는 것이 더 나을 것입니다.

잘 모르겠 으면 std::tuple을 사용하여 향후 API 설계 유연성을 유지하십시오.

또 다른 방법은 분명 같은 값에 대한 의미를 명명 한 자신의 구조체를 사용하는 것입니다 : 주변에 여러 값을 포장하기위한 의미

template<typename T> 
struct point2D { 
     T x; 
     T y; 
}; 

template<typename T> 
struct point3D { 
     T x; 
     T y; 
     T z; 
}; 

template<typename Key, typename Value> 
struct Item { 
    Key key: 
    Value value; 
}; 

보다는 std::tuple<T,T>, std::pair<T,T> 또는 std::tuple<T,T,T>

0

튜플을 그 서로 관계가있을 수도 있고 없을 수도 있습니다.

쌍은 서로간에 관계가있는 두 쌍의 값을 묶는 데 사용됩니다. 키 - 값 쌍은 두 개의 값을 가지며, 하나는 키이고 다른 하나는 값입니다. 둘 다 서로 서로 관계가 있습니다. 해시 맵에서 키는 쌍 또는 값을 가리 킵니다.

정말 당신이 모든 등

+4

아니, 그게 쌍을 의미하지 않습니다. 표준 라이브러리에서 부적절하게 사용 된 것입니다. 키 - 값 쌍이있는 경우 해당 구조는 key라는 멤버와 value라는 멤버가있는 구조체입니다. –

0

내가 일반적으로 본 적이 적절한 API 호출 또는 라이브러리 (관련 수학) 작업 컨테이너가 두 개의 값이있는 경우에도 구조체 나 클래스를 반환하는 방법에 온다.

값이 키 값 쌍인 경우 반드시 @Bauss에 동의해야합니다. 예를 들어, "table id, string name"과 같이 std::pair을 사용하십시오.

그러나 터플이 키 값이 아니지만 둘 다 실제 값인 경우 예를 들어 위치가 XY 좌표 (int x, int y) 인 경우 std::tuple을 사용하십시오.

+0

글쎄요, 2D 좌표 포인트와 같이'std :: pair '를 사용하는 것은 적용되지 않습니다. –

+2

내가 사용했던 프레임 워크 나 lib는 좌표 점을 포함하기 위해'std :: pair' 나'std :: tuple'을 사용하지 않았습니다. 예를 들어 OpenFramework는 Vec2f를 사용하고 Qt는 QPoint를 사용하고 UDK는 FVector2D 등을 사용합니다. – ArmenB

+0

@ArmenB : ... 특히 페어와 튜플은 일반적인 연산자 오버로딩을 놓치기 때문에 좌표 점으로 사용하는 것이 훨씬 더 어색합니다. –

0

경고 : 다음 무엇의 일부 의견입니다 :

  • 제로
  • 하나
  • N

때문에 :

컴퓨터 과학에서

, 오직 세 가지 흥미로운 숫자가있다 우리는 무언가, 한 가지 또는 몇 가지의 부재를 다루고 있습니다. 예를 들어 average(a0 , a1)average(a0, ...aI)의 특수한 경우이며, 여기서 I는 집합의 모든 정수입니다 (0 < = I < N).

std::pair은 논리적으로 N- 튜플을 특수화하므로 불필요한 것입니다.

최악의 경우 pair을 사용하면 항목 수가 항상 2로 가정하고 인터페이스로 구워집니다. 이것은 분명히 오류입니다. 왜냐하면 우리는 제로 이득을 위해 미래의 획기적인 변경을 할 수있는 능력을 거래하고 있기 때문입니다.

STL과 처음에는 가변 인자 템플릿이 없었다 단지 세 가지 사용 사례가 쌍을 위해 거기 작성되었습니다

: - equal_range에 따른 범위로

  1. 와 같은 등

  2. 반복기가있는 상태는 map에서 map::insert

  3. 의 키/값 쌍으로 반환됩니다.

그런 다음 튜플과 같은 현대적인 아이디어가 추가되었습니다. 비공식 라이브러리이기 때문에 boost는 자동 생성 된 오버로드 페이지 및 페이지로 다양한 템플릿을 시뮬레이션 할 수있었습니다. 모든 컴파일러와 함께 제공되는 표준화 된 API에서는 상상도 못할 것입니다.

이제 variadic 템플릿이 있습니다. 안타깝게도지도의 인터페이스에 구운 경우를 제외하고는 tuple보다 pair을 선호 할 이유가 없습니다.

+1

STL이 작성된 경우에도'std :: pair '를 반환하는 결정은 매우 가난한 결정이었습니다. 명명 된 구조체가 훨씬 더 좋았을 것입니다. 'auto i = map.insert (key, value); if (i.first) {/ * or i.second? 기억할 수 없다 ... * /}'. – peppe

+1

"* 더 나쁜 것은 한 쌍을 사용하면 항목 수가 항상 2가 될 것이라고 가정하고이를 인터페이스로 굽는 것입니다. *"함수는 매개 변수의 수에 구워지지 않았기 때문에. 오 기다려 ... "* 튜플보다 한 쌍을 더 선호 할 이유가 없다. *"당신이 쉽게 복사 및/또는 표준 레이아웃이 필요한 유형이 아니라면. '튜플 '도 아니다. –

+1

@NicolBolas이 표준 레이아웃 사례를 고려하지 않았다는 것은 사실입니다. 그러나 그러한 경우에는 3 줄의 코드 (중괄호 제외)에서이 작업을 수행하는 새로운 구조체를 만드는 것이 더 표현적이고 사소한 것 같습니다.표준 레이아웃 2- 튜플이 정말로 필요한 경우 간단한 구조체를 사용하여 std :: tie를 사용하여 동일한 효과를 얻을 수 있습니다. 나는 의견의 존재에 대한 경고를했다. –