C ++ 20 'requires'표현식에서 지정되지 않은 유형을 어떻게 사용할 수 있습니까?
저는 C ++ 20 개념을 작성하여 유형에 인수를받는 특정 메서드가 있어야한다는 요구 사항을 표현하려고하지만이 개념의 목적 상 인수 유형이 무엇인지는 신경 쓰지 않습니다.
다음과 같이 작성하려고했습니다.
template <typename T>
concept HasFooMethod = requires(T t, auto x)
{
{ t.Foo(x) } -> std::same_as<void>;
};
그러나 gcc와 clang은 모두이를 거부하여 require 표현식의 매개 변수 목록에서 이러한 방식으로 'auto'를 사용할 수 없다는 오류를 표시합니다.
대안은 'x'유형을 두 번째 템플릿 매개 변수로 넣는 것입니다.
template <typename T, typename TX>
concept HasFooMethod = requires(T t, TX x)
{
{ t.Foo(x) } -> std::same_as<void>;
};
그러나 이것은 개념이 사용될 때마다 TX를 명시 적으로 지정해야하며 추론 할 수 없습니다.
struct S { void Foo(int); };
static_assert(HasFooMethod<S>); // doesn't compile
static_assert(HasFooMethod<S, int>); // the 'int' must be specified
Foo가 지정되지 않은 유형 의 인수를 취할 수있는 개념을 작성하는 방법이 있습니까?
제한된 템플릿 멤버 함수를 요구하는 개념 정의 라는 질문 은 매우 유사하지만 동일하지는 않습니다.이 질문은 (템플릿) 메서드가 주어진 개념을 충족하는 모든 유형을 취할 수 있도록 요구하는 방법을 묻는 반면,이 질문은 메서드가 일부 특정 유형의 해당 유형은 지정되지 않습니다,하지만. 수량화 측면에서 다른 질문은 (제한된) 보편적 수량화에 대해 묻는 것이고, 이것은 실존 적 수량화에 관한 것입니다. 다른 질문의 답변도 제 경우에 적용되지 않습니다.
답변
개념은 원하는 기능을 제공하기위한 것이 아닙니다. 그래서 그들은 그것을 제공하지 않습니다.
개념은 템플릿을 제한하고 템플릿이 정의에서 사용하려는 (또는 최소한 자유롭게 사용할 수있는) 식 또는 문 집합을 지정하기위한 것입니다.
템플릿 내에서 당신은 그래서 당신은 식을 작성하는 경우, 구속되어 t.Foo(x)
, 다음의 유형을 알고있다 x
. 구체적인 유형, 템플릿 매개 변수 또는 템플릿 매개 변수에서 파생 된 이름입니다. 어느 쪽이든 x
제한되는 템플릿에서 유형을 사용할 수 있습니다.
따라서 이러한 템플릿을 제한하려면의 유형 t
과 유형을 모두 사용합니다 x
. 그 때 둘 다 사용할 수 있으므로 이러한 제약을 만드는 데 문제가 없습니다. 즉, 제약 조건이 T
격리 된 유형으로 설정 되어 있지 않습니다 . 그것은 사이의 연관에의 T
와 X
.
개념은 제약 조건의 실제 사용 위치와 관련이없는 진공 상태에서 작동하기위한 것이 아닙니다. 사용자가 static_assert
자신의 클래스에 맞설 수 있도록 단항 개념을 만드는 데 집중해서는 안됩니다 . 개념은 유형이이를 충족하는지 테스트하기위한 것이 아닙니다 (기본적으로 static_assert
수행하는 작업입니다). 그것들을 사용 하는 템플릿 정의를 제한하기위한 것입니다.
귀하의 제약 요구가되게 FooCallableWith
하지 HasFooMethod
.
이와 유사한 것은 암시 적으로 (거의) 무엇이든 변환 할 수있는 어댑터 유형을 정의하여 수행 할 수 있습니다.
struct anything
{
// having both these conversions allows Foo's argument to be either
// a value, an lvalue reference, or an rvalue reference
template <typename T>
operator T&();
template <typename T>
operator T&&();
};
이러한 연산자는 평가되지 않은 컨텍스트에서만 사용되므로 구현할 필요가 없습니다 (실제로 모든 유형 T에 대해 구현할 수 없음).
그런 다음 다음과 HasFooMethod
같이 작성할 수 있습니다.
template <typename T>
concept HasFooMethod = requires(T t, anything a)
{
{ t.Foo(a) } -> std::same_as<void>;
};