개념을 함수에 전달


12

개념은 컴파일 타임 술어로 정의되므로 실제로 컴파일 타임 알고리즘에 이러한 술어를 재사용 할 수 있습니까? 예를 들어 튜플의 모든 유형이 개념을 준수하는지 확인할 수 있습니까? 내가 본 한, 어떤 식 으로든 개념을 함수에 전달하는 것은 불가능합니다.이 경우 이러한 경우에 템플릿을 사용하게됩니다.

#include <type_traits>

template<typename T>
concept FloatLike = std::is_same_v<T, float>;

struct IsFloat
{
    template<typename U>
    constexpr static bool test()
    {
       return FloatLike<U>;
    }
};


template<typename Predicate, typename... T>
constexpr bool all_types()
{
    return (Predicate::template test<T>() && ...);
}


int main()
{
   static_assert(all_types<IsFloat, float, float>());
   static_assert(!all_types<IsFloat, float, int>());
}

내가하고 싶은 것은 다음과 같은 것이므로 개념을 사용할 수 있도록 항상 개념을 감쌀 필요는 없습니다.

template<concept Predicate, typename... T>
constexpr bool all_types()
{
    return (Predicate<T> && ...);
}


int main()
{
   static_assert(all_types<FloatLike, float, float>());
   static_assert(!all_types<FloatLike, float, int>());
}

이것에 더 가까이 갈 수있는 방법이 있습니까?


그리고 개념의 개념을 추가하라는 제안이있을 것입니다 ... BTW, all_types()접는 표현을 사용하여 크게 단순화 될 수 있습니다 ... &&.return (... && Predicate::template test<Ts>());
Evg

@Evg 그것은 위대한 것입니다 :)
Igor R.

답변:


5

이것에 더 가까이 갈 수있는 방법이 있습니까?

아뇨 C ++ 20에는 없습니다. 오늘날 템플릿 개념 매개 변수에 대한 개념은 없습니다. 변수 템플릿도 템플릿 매개 변수로 사용할 수 없습니다. 따라서 시작하는 개념이 있으면 줄 바꿈을 피할 수 없습니다.

그러나 우리가 할 수있는 것은 더 간단한 래퍼를 작성하는 것입니다. "오래된 스타일"유형의 특성을 술어, 특히 std::integral_constants 처럼 행동하는 특성으로 사용하기로 동의하면 술어로 사용할 수있는 아주 "개념"정의를 가질 수 있습니다.

template<typename T>
using FloatLike = std::is_same<T, float>;

template<template <typename> class Predicate, typename... T>
constexpr bool all_types()
{
    return (Predicate<T>{} && ...);
}

내가 볼 수있는 한 , 얻을 수있는 한 좋습니다 .


어떤 식 으로든 일반적인 람다를 템플릿 템플릿으로 선언하여 작동합니까? 람다는 올바른 템플릿이 아니라 호출 연산자 인 것처럼 보입니다.
Andreas Loanjoe

@AndreasLoanjoe-참으로. 람다는 결코 템플릿이 아닙니다. 그러나 람다를 기꺼이 통과 시키려면 C ++ 20을 사용하면됩니다. 몇 분 안에 변형을 추가 할 수 있습니다.
StoryTeller-Unslander Monica

@AndreasLoanjoe-두 번째 생각에 람다는 여전히 매우 장황합니다. 나는 그것이 훌륭한 대안이라고 생각하지 않습니다. 여기는 어쨌든 godbolt.org/z/QSHy8X
StoryTeller-Unslander Monica

나는 그들이 더 나은 것을 추가하기를 희망합니다 :), 그렇습니다. 이것이 답 인 것처럼 보입니다. 스타일 유형 특성 만이이 기능 개념을 제공하지 않습니다 (아직).
Andreas Loanjoe

0

목표가 "튜플의 모든 유형이 개념을 따르는 지 확인"하는 경우 다음과 같이 할 수 있습니다.

// concept to check if all types in Ts are the same as T
template<typename T, typename... Ts>
concept AllSame = (std::is_same_v<T,Ts> && ...);

// function only accepts floats as template parameters
template<AllSame<float>... Floats>
constexpr void float_foo()
{
}

// function only accepts ints as template parameters
template<AllSame<int>... Ints>
constexpr void int_foo()
{
}

// function only accepts T as template parameters
template<typename T, AllSame<T>... Ts>
constexpr void foo()
{
}

int main()
{
    int_foo<int, int, int>();
    // int_foo<int, int, double>(); // fails to compile
    float_foo<float, float, float>();
    // float_foo<float, float, int>(); // fails to compile
    foo<int, int, int, int>();
    // foo<int, int, int, float>(); // fails to compile
    foo<double, double, double, double>();
    // foo<double, double, double, int>(); // fails to compile

}

라이브 데모


AllSame변덕스러운가요? 형식 제약 조건에 의해 도입 된 팩의 각 템플릿 매개 변수는 이미 별도로 제한되어 있습니다.
Davis Herring

@DavisHerring 이해가되지 않습니다. 개념 자체 또는 템플릿 매개 변수를 의미 *_foo()합니까?
kanstar

난 당신이 작품이 코드는 당신이를 제거하면 의미 ...Ts&& ...그것을 사용하는. (분명히 그 이름 AllSame은 부적절 할 것이지만, 어쨌든 왜 단항으로 카운트를 표현하고 싶은지 잘 모르겠습니다 <int,int,int>.)
Davis Herring

@DavisHerring 그러면 컨셉은 AllSame아니지만 SameAs( en.cppreference.com/w/cpp/concepts/same_as 참조 ) OP는 다양한 템플릿 매개 변수를 취하는 컨셉을 원했습니다.
kanstar

분명히 그렇습니다 std::same_as. 나는 variadic 부분이 요점이라고 생각하지 않는다 : 그것은 개념 의 (바람직한) 가변적 정체성 이었다. 그리고 내 요점은 당신의 개념 예제의 variadic 측면은 그것의 사용과 관련이 없다는 것입니다 (변하지 않은 개념은 이미 템플릿 매개 변수 팩과 함께 작동하기 때문입니다).
Davis Herring
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.