使用模板和decltype
时,即使您没有时间,也经常需要某种类型的实例。在这种情况下,std::declval<T>()
非常有用。这将创建一个T
类型的虚构实例。
概念是否有类似之处?即可以为概念创建虚构类型的函数。
让我给你一个例子(有点作弊,但应该达到目的):
让我们定义一个概念Incrementable
template <typename T>
concept Incrementable = requires(T t){
{ ++t } -> T;
};
现在,我想提出一个概念来测试对象是否具有可以接受operator()
的运算符Incrementable
。用我虚构的语法,我会这样写:
template <typename F, typename T = declval<Incrementable>>
concept OperatesOnIncrementable = requires(F f, T t){
{ f(t) } -> T;
}
declval
中的typename T = declval<Incrementable>
会创建一个虚构的类型T
,它实际上不是一个具体的类型,但对于所有意图和目的,其行为都类似于满足Incrementable
的类型。
即将到来的标准中是否存在允许这种情况的机制?我会发现这非常有用。
编辑:前段时间我问过similar question是否可以用boost::hana
来完成。
编辑:为什么这有用?例如,如果您要编写一个包含两个函数的函数
template <typename F, typename G>
auto compose(F f, G g) {
return [f, g](Incrementable auto x) { return f(g(x)); };
}
当我尝试组合两个无法组合的函数时,我想得到一个错误。在不限制类型F
和G
的情况下,只有在尝试调用组合函数时才会出现错误。
答案 0 :(得分:7)
没有这种机制。
这似乎也不是可实现的/有用的,因为存在Incrementable
类型的无限数量,并且F
可以拒绝使用任意复杂的元程序选择的子集。因此,即使您可以神奇地合成某些唯一类型,也无法保证F
对所有Incrementable
类型都有效。
答案 1 :(得分:4)
概念是否有类似之处?即可以为概念创建虚构类型的函数。
此术语是原型。提出原型将是非常有价值的功能,并且对于进行定义检查等操作至关重要。来自T.C.的答案:
因此,即使您可以神奇地合成某些唯一类型,也无法保证
F
对所有Incrementable
类型都有效。
做到这一点的方法是合成一个尽可能最小地满足该概念标准的原型。正如他所说,C ++ 20中没有原型生成,并且鉴于当前的概念化,这似乎是不可能的。
提出正确的原型非常困难。例如,对于
template <typename T>
concept Incrementable = requires(T t){
{ ++t } -> T;
};
很容易写:
struct Incrementable_archetype {
Incrementable_archetype operator++();
};
但这并不是“尽可能的少”-这种类型是默认可构造和可复制的(不是Incrementable
提出的要求),并且它的operator++
返回的恰好是T
,即也没有要求。因此,一个真正的核心原型将如下所示:
struct X {
X() = delete;
X(X const&) = delete;
X& operator=(X const&) = delete;
template <typename T> operator,(T&&) = delete;
struct Y {
operator X() &&;
};
Y operator++();
};
如果您的函数适用于X
,那么它可能适用于所有Incrementable
类型。如果您的函数不适用于X
,则可能需要更改实现以使其实现,或者更改约束以允许更多功能。
有关更多信息,请查看Boost Concept Check Library,它虽然很旧,但是至少阅读文档非常有趣。