개념을 함수에 전달 constexpr static bool test()

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

#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>());
}

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



답변

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

아뇨 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>{} && ...);
}

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


답변

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

// 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

}

라이브 데모


답변