将概念传递给函数
Posted
技术标签:
【中文标题】将概念传递给函数【英文标题】:Passing a concept to a function 【发布时间】:2020-03-11 12:52:16 【问题描述】:由于概念被定义为编译时谓词,是否也可以将这些谓词实际重用于编译时算法?例如,是否可以检查元组中的所有类型是否都符合一个概念?据我所知,不可能以任何方式,这让我回到了在这些情况下使用模板。
#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>());
有没有办法接近这个?
【问题讨论】:
然后会有增加概念概念的提议...顺便说一句,all_types()
可以使用折叠表达式大大简化... &&
:return (... && Predicate::template test<Ts>());
@Evg 会很棒 :)
【参考方案1】:
如果你的目标是“检查一个元组中的所有类型是否符合一个概念”,那么你可以这样做:
// 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
LIVE DEMO
【讨论】:
为什么你的AllSame
是可变参数? type-constraint 引入的包中的每个模板参数都已单独受到约束。
@DavisHerring 我不明白。你是指概念本身还是*_foo()
中的模板参数?
我的意思是,如果你删除 Ts
上的 ...
和使用它的 && ...
,你的代码就可以工作。 (显然AllSame
这个名字不合适,但我不知道为什么我要把一元计数表示为<int,int,int>
。)
显然是std::same_as
。我不认为可变参数部分是重点:它是概念的(期望的)变量identity。我的观点是,您的概念示例的可变参数方面与其使用无关(因为非可变参数概念已经与模板参数包一起使用)。【参考方案2】:
有没有办法接近这个?
嗯,不,不是真的。不在 C++20 中。今天的语言中没有模板概念参数的概念。甚至变量模板也不能用作模板参数。所以如果有一个概念开始,我们就不能避免包装。
但我们可以做的是编写更简单的包装器。如果我们同意使用“旧式”类型特征作为谓词,特别是那些行为类似于 std::integral_constant
s 的特征,那么我们可以拥有可以用作谓词的非常简洁的“概念”定义。
template<typename T>
using FloatLike = std::is_same<T, float>;
template<template <typename> class Predicate, typename... T>
constexpr bool all_types()
return (Predicate<T> && ...);
就我所见,它和it can get 一样好。
【讨论】:
是否可以通过以任何方式将通用 lambda 类型化为模板模板来实现?似乎 lambda 从来都不是模板,虽然对,只有调用运算符? @AndreasLoanjoe - 确实。 lambda 永远不是模板。但是,如果您愿意传递 lambda,那么 C++20 允许您这样做。我可以在几分钟内添加一个变体。 @AndreasLoanjoe - 再三考虑,lambda 仍然非常冗长。我不认为这是一个很好的选择。无论如何godbolt.org/z/QSHy8X 我希望他们能添加一些更好的东西 :),但是看起来这就是答案,只有样式类型特征确实提供了这个功能概念(还没有)。以上是关于将概念传递给函数的主要内容,如果未能解决你的问题,请参考以下文章
Ember hbs模板是否应该将参数从输入字段传递给函数,如果是这样的话?
C语言基础:指针相关概念(指针的算术运算 指针数组指向指针的指针 传递指针给函数 从函数返回指针 )为啥C 语言不支持在调用函数时返回局部变量的地址?