개념과 템플릿 제약의 차이점은 무엇입니까?


96

C ++ 전체 개념 제안과 템플릿 제약 (예 : Dlang에 나타난 제약 또는 C ++ 1y에 대한 새로운 concepts-lite 제안) 사이의 의미 적 차이점을 알고 싶습니다 .

템플릿 제약이 할 수없는 것보다 할 수있는 본격적인 개념은 무엇입니까?


2
제약 제안 이 여기에 포함됩니다.
chris

나는 4.8 Designing Concepts를 회상 하고 있었지만 실제로 개념이 더 많은 제약을받는 방식에 대해서는 많이 나열되지 않았습니다. 인터넷 검색 개념은 이제 제안에서 제약 조건을 더 잘 이해 한 후 쉽게 발견 할 수있는 차이점을 보여줄 수 있습니다.
chris

IMHO 개념은 '프로그래밍 요소'에서 Alexander Stepanov와 같은 사람들이 오래 전에 요청한대로 가독성을 향상시키고보다 명확한 프로그래밍 기능을 제공합니다. 라이트 제안은 현재 필요한 이상한 enable_if 유형 제약의 부담을 덜어주기위한 것입니다. 제네릭 프로그래밍은 빠를수록 좋습니다.
dirvine

답변:


136

다음 정보는 오래되었습니다. 최신 Concepts Lite 초안에 따라 업데이트해야합니다.

제약 제안 의 섹션 3 은이를 합리적인 깊이로 다룹니다.

개념 제안 은 제약 (예 : concepts-lite)이 더 짧은 시간 단위로 구체화되고 구현 될 수 있기를 바라면서 잠시 동안 뒤로 버너에 올려 져 현재 C ++ 14에서 적어도 무언가를 목표로하고 있습니다. 제약 제안은 이후의 개념 정의로 원활하게 전환되도록 설계되었습니다. 제약은 개념 제안의 일부이며 정의에 필요한 구성 요소입니다.

에서 C ++에 대한 개념 라이브러리의 설계 , 서튼과 스트로브 스트 룹은 다음과 같은 관계를 고려 :

개념 = 제약 + 공리

그 의미를 빠르게 요약하려면 :

  1. Constraint-유형의 정적으로 평가 가능한 속성에 대한 조건 자입니다. 순전히 구문 요구 사항. 도메인 추상화가 아닙니다.
  2. 공리-참이라고 가정되는 유형의 의미 론적 요구 사항. 정적으로 확인되지 않았습니다.
  3. 개념-인수에 대한 알고리즘의 일반적인 추상 요구 사항. 제약과 공리로 정의됩니다.

따라서 제약 (구문 속성)에 공리 (의미 속성)를 추가하면 개념을 얻을 수 있습니다.


개념-라이트

concepts-lite 제안은 우리에게 첫 번째 부분 인 제약만을 가져 오지만 이것은 완전한 개념을 향한 중요하고 필요한 단계입니다.

제약

제약은 모두 구문 에 관한 것 입니다. 컴파일 타임에 유형의 속성을 정적으로 식별하는 방법을 제공하므로 구문 속성을 기반으로 템플릿 인수로 사용되는 유형을 제한 할 수 있습니다. 제약 조건에 대한 현재의 제안에, 그들은 명제 논리의 부분 집합이 같은 논리 연산을 사용하여 표현 &&하고 ||.

작동중인 제약 조건을 살펴 보겠습니다.

template <typename Cont>
  requires Sortable<Cont>()
void sort(Cont& container);

여기서 우리는라는 함수 템플릿을 정의합니다 sort. 새로 추가 된 것은 requires 절 입니다. requires 절은이 함수의 템플릿 인수에 대한 몇 가지 제약 조건을 제공합니다. 특히이 제약 조건은 유형이 유형 Cont이어야 함을 나타냅니다 Sortable. 깔끔한 점은 다음과 같이보다 간결한 형식으로 작성할 수 있다는 것입니다.

template <Sortable Cont>
void sort(Cont& container);

이제이 Sortable함수로 간주되지 않는 것을 전달하려고하면 추론 TSortable유형이 유형 이 아니라는 것을 즉시 알려주는 멋진 오류가 발생합니다 . C ++ 11에서이 작업을 수행했다면 누구에게도 말이되지 않는 함수 내부 에서 발생한 끔찍한 오류가 발생했을 것 sort입니다.

제약 조건 술어는 유형 특성과 매우 유사합니다. 템플릿 인수 유형을 취하고 이에 대한 정보를 제공합니다. 제약 조건은 유형에 대한 다음과 같은 유형의 질문에 답하려고합니다.

  1. 이 유형에 이러한 연산자가 오버로드되어 있습니까?
  2. 이러한 유형을이 연산자의 피연산자로 사용할 수 있습니까?
  3. 이 유형에는 그런 특성이 있습니까?
  4. 이 상수 표현이 저것과 같습니까? (비 유형 템플릿 인수의 경우)
  5. 이 유형에 해당 유형을 반환하는 yada-yada라는 함수가 있습니까?
  6. 이 유형은 사용되는 모든 구문 요구 사항을 충족합니까?

그러나 제약 조건은 유형 특성 을 대체하기 위한 것이 아닙니다 . 대신 그들은 함께 일할 것입니다. 일부 유형 특성은 이제 개념 측면에서 정의되고 일부 개념은 유형 특성 측면에서 정의 될 수 있습니다.

따라서 제약에 대한 중요한 것은 그들이 의미론에 관심이 없다는 것입니다. 제약 조건의 좋은 예는 다음과 같습니다.

  • Equality_comparable<T>: 유형 ==에 동일한 유형의 두 피연산자 가 있는지 확인합니다 .

  • Equality_comparable<T,U>: ==지정된 유형의 왼쪽 및 오른쪽 피연산자 가 있는지 확인합니다.

  • Arithmetic<T>: 유형이 산술 유형인지 확인합니다.

  • Floating_point<T>: 유형이 부동 소수점 유형인지 확인합니다.

  • Input_iterator<T>: 입력 반복기가 지원해야하는 구문 연산을 유형이 지원하는지 확인합니다.

  • Same<T,U>: 주어진 유형이 동일한 지 확인합니다.

이 모든 것을 GCC 의 특별한 concepts-lite 빌드로 시도 할 수 있습니다 .


개념을 넘어서 라이트

이제 우리는 concepts-lite 제안을 넘어선 모든 것에 들어갑니다. 이것은 미래 자체보다 훨씬 미래 적입니다. 여기서부터는 모든 것이 상당히 변경 될 것입니다.

공리

공리는 의미론 에 관한 것 입니다. 관계, 불변, 복잡성 보장 및 기타 사항을 지정합니다. 예를 살펴 보겠습니다.

그동안 Equality_comparable<T,U>제약이 거기 있음을 알려드립니다 operator== 유형을 소요 T하고 U, 그것은 당신에게 어떤 것을 조작 말하지 않는 방법을 . 이를 위해 우리는 공리를 가질 것 Equivalence_relation입니다. 이 공리는 두 가지 유형의 개체를 비교하면 말한다 operator==주고 true, 이러한 개체는 동일합니다. 중복 된 것처럼 보일 수 있지만 확실히 그렇지 않습니다. 당신은 쉽게 정의 할 수 있습니다 operator==대신처럼 행동 것을 operator<. 그렇게하는 것은 사악하지만 할 수 있습니다.

또 다른 예는 Greater공리입니다. 두 가지 유형의 객체 T><연산자 와 비교할 수 있다고 말하는 것이 좋습니다 . 그러나 그 의미는 무엇입니까? Greater공리는 IFF는 말한다 x다음 큰 y다음 y보다 작 x. 공리와 같은 제안 된 사양은 다음과 같습니다.

template<typename T>
axiom Greater(T x, T y) {
  (x>y) == (y<x);
}

따라서 공리는 다음 유형의 질문에 답합니다.

  1. 이 두 연산자가 서로이 관계를 가지고 있습니까?
  2. 이런 유형의 연산자가 이것을 의미합니까?
  3. 해당 유형에 대한이 작업이 이처럼 복잡합니까?
  4. 이 연산자의 결과가 이것이 사실임을 의미합니까?

즉, 이러한 유형에 대한 유형 및 작업의 의미론과 전적으로 관련됩니다. 이러한 것들은 정적으로 확인할 수 없습니다. 이것이 확인되어야한다면, 타입은 어떤 식 으로든 그것이 이러한 의미론을 준수 함을 선언해야합니다.

다음은 공리의 몇 가지 일반적인 예입니다.

  • Equivalence_relation: 두 객체가 비교 ==되면 동등합니다.

  • Greater: 때마다 x > y, 다음 y < x.

  • Less_equal: 때마다 x <= y, 다음 !(y < x).

  • Copy_equality: For xand yof type T: if x == y, 복사 생성에 의해 생성 된 동일한 유형의 새 객체 T{x} == y이며 여전히 x == y비파괴 적입니다.

개념

이제 개념을 정의하기가 매우 쉽습니다. 그것들은 단순히 제약과 공리조합입니다 . 형식의 구문과 의미에 대한 추상적 인 요구 사항을 제공합니다.

예를 들어 다음 Ordered개념을 고려하십시오 .

concept Ordered<Regular T> {
  requires constraint Less<T>;
  requires axiom Strict_total_order<less<T>, T>;
  requires axiom Greater<T>;
  requires axiom Less_equal<T>;
  requires axiom Greater_equal<T>;
}

템플릿 유형에 대한 우선 참고 TOrdered, 또한의 요구 사항을 충족해야합니다 Regular개념. Regular개념은 유형이 올바르게 동작하는 것을 아주 기본적인 요구 사항입니다 - 그것은, 구축 파괴, 복사와 비교 될 수있다.

이러한 요구 사항 외에도 하나의 제약 조건과 네 가지 공리 OrderedT충족 하는 요구 사항 :

  • 제약 : Ordered유형에는 operator<. 이것은 정적으로 확인되므로 존재 해야 합니다.
  • 공리 : For xand yof type T:
    • x < y 엄격한 총 주문을 제공합니다.
    • x보다 큰 y, y보다 작은 x, 그리고 그 반대의 경우도 마찬가지입니다.
    • x미만 또는 동일 y, y이하보다 x, 그 반대의 경우도 마찬가지입니다.
    • 경우 x이상인 경우 y, y보다 큰 경우 x, 그 반대.

이와 같은 제약과 공리를 결합하면 개념이 제공됩니다. 알고리즘과 함께 사용할 추상 유형에 대한 구문 및 의미 요구 사항을 정의합니다. 알고리즘은 현재 사용되는 유형이 특정 작업을 지원하고 특정 의미를 표현할 것이라고 가정해야합니다. 개념을 통해 요구 사항이 충족되는지 확인할 수 있습니다.

에서 최신 개념 디자인 , 컴파일러는 단지 개념의 구문 요구 사항은 템플릿 인수에 의해 충족되어 있는지 확인합니다. 공리는 확인되지 않은 상태로 남아 있습니다. 공리는 정적으로 평가할 수없는 (또는 종종 완전히 확인하는 것이 불가능한) 의미를 나타 내기 때문에 유형 작성자는 해당 유형이 개념의 모든 요구 사항을 충족한다고 명시 적으로 설명해야합니다. 이것은 이전 디자인에서 개념 매핑으로 알려졌지만 이후 제거되었습니다.

다음은 개념의 몇 가지 예입니다.

  • Regular 유형은 생성 가능하고 파괴 가능하며 복사 가능하며 비교할 수 있습니다.

  • Ordered유형은를 지원 operator<하고 엄격한 총 순서 및 기타 순서 의미를 갖습니다.

  • Copyable유형 destructable, constructable 복사하고, 경우 xIS가 동일 y하고 x복사, 복사도 동일한 비교합니다 y.

  • Iterator유형이 관련된해야합니다 유형은 value_type, reference, difference_type, 그리고 iterator_category자체는 특정 개념을 충족해야한다. 또한 지원 operator++하고 역 참조 할 수 있어야합니다 .

개념으로가는 길

제약 조건은 C ++의 전체 개념 기능을 향한 첫 번째 단계입니다. 훨씬 더 깔끔한 템플릿 함수와 클래스를 작성할 수 있도록 유형의 정적으로 시행 가능한 요구 사항을 제공하기 때문에 매우 중요한 단계입니다. 이제 우리는 std::enable_if메타 프로그래밍 친구들 의 어려움과 추함을 피할 수 있습니다 .

그러나 제약 제안이 수행하지 않는 여러 가지가 있습니다.

  1. 개념 정의 언어를 제공하지 않습니다.

  2. 제약은 개념도가 아닙니다. 사용자는 특정 제약 조건을 충족하기 위해 유형에 특별히 주석을 달 필요가 없습니다. 간단한 컴파일 타임 언어 기능을 사용하여 정적으로 확인됩니다.

  3. 템플릿의 구현은 템플릿 인수에 대한 제약에 의해 제한되지 않습니다. 즉, 함수 템플릿이 수행해서는 안되는 제한된 유형의 객체로 작업을 수행하는 경우 컴파일러는이를 진단 할 방법이 없습니다. 완전한 기능을 갖춘 개념 제안이이를 수행 할 수 있습니다.

제약 제안은 그 위에 완전한 개념 제안이 도입 될 수 있도록 특별히 설계되었습니다. 운 좋게도 그 전환은 상당히 순조롭게 진행되어야합니다. 개념 그룹은 C ++ 14 (또는 곧 기술 보고서에서)에 대한 제약 조건을 도입하려고하는 반면 전체 개념은 언젠가 C ++ 17 주변에서 나타나기 시작할 수 있습니다.


5
concepts-lite는 템플릿 자체의 구현에 대한 제약 조건을 확인하지 않습니다. 따라서 DefaultConstructable을 사용할 수 있다고 주장 할 수 있지만 컴파일러가 실수로 복사 생성자를 사용하는 것을 막지는 않습니다. 더 완전한 기능을 갖춘 개념 제안이 될 것입니다.
Nicol Bolas 2013 년

24
즉, A는 첫 번째 초안은?
Nicol Bolas 2013 년

2
@sftrabbit, 아주 좋은 대답입니다. 그러나 질문이 있습니다. 컴파일러가 유형이 개념의 의미 요구 사항을 충족하는지 확인하는 방법은 무엇입니까?
Rayniery 2013 년

1
(많은 불확실성이있는) 런타임 중에 'axioms'가 확인됩니까, 아니면 일종의 promise 태그로만 제공됩니까?
Red XIII

4
@ScarletAmaranth : 한정된 시간 내에 정리를 자동으로 증명하는 것으로 귀결되기 때문입니다. 여기에는 두 가지 장애물이 있습니다. 1. 이론상 극히 어렵고 현재 기술로는 불가능한 유한 한 시간 내에 정리를 증명합니다. 2. 증명이 다른 공리에 기초하지 않는 한 공리를 증명할 수 없습니다. (이 경우 수학적으로 "공리가 아님"이됩니다.)이 공리는 컴파일러에게 "유용하다고 생각되면 비교를 되돌릴 수 있습니다 ..."또는 "예, 항상 교차로에서 사용되는 EmptySet 동일한 결과를 제공합니다. "
Laurent LA RIZZA 2013-06-26


4

내 2 센트 :

  1. concepts-lite 제안은 템플릿 구현 의 "유형 검사"를 수행하기위한 것이 아닙니다 . 즉, Concepts-lite는 템플릿 인스턴스화 사이트에서 (의견 상) 인터페이스 호환성을 보장합니다. 논문에서 인용 : "concepts lite는 템플릿 인수를 제한하기 위해 술어를 사용할 수있는 C ++의 확장입니다." 그리고 그게 다야. 템플릿 본문이 술어에 대해 (격리 상태로) 검사된다는 것은 아닙니다. 그것은 아마도 당신이 concepts-lite에 대해 이야기 할 때 아키 타입에 대한 일류 개념이 없다는 것을 의미 합니다. 내가 정확하게 기억한다면, 개념이 많은 제안에서 archtype 은 템플릿 의 구현 을 만족시키기 위해 더 이상 제공하지 않는 유형입니다 .

  2. concepts-lite는 컴파일러가 지원하는 약간의 구문 트릭과 함께 영광스러운 constexpr 함수를 사용합니다. 조회 규칙이 변경되지 않았습니다.

  3. 프로그래머는 개념 맵을 작성할 필요가 없습니다.

  4. 마지막으로, "제약 제안은 의미론의 지정이나 사용을 직접적으로 다루지 않습니다. 단지 구문 검사만을 목표로합니다." 이는 공리가 (지금까지) 범위 내에 있지 않음을 의미합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.