개념을 함수에 전달


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.