用于检查容器类中是否存在函数和隐式演绎规则的C++概念
我正在尝试解决一些在概念和模板类型(如std::VECTOR)方面对我来说似乎很棘手的事情。
我正在尝试应用编译时间约束,类似于我在T上使用std::move的方式,但在C上使用PushBackMoovable时。它与函数Decl末尾的Requires一起工作,但我希望保持一致,并将我的约束放在模板args中。我试着用"PushBackMoovable C"替换"C类",但失败得不是很严重,但更接近我想要的。
我正在尝试使用模板模板参数中的模板类型。
2A。有没有办法只声明C,并在它的签名内使用模板参数 功能呢?例如,我可以去掉"T"和"Alalc",而使用"_T"和"_Allc"吗?似乎 我不能访问这些参数。我想节省一些代码空间。
2B。它们是否可以删除运算符第一个参数上C上的空<;>?
2C。如果我刚刚有了PushBackMoable,编译器可以在Requires上推导出C的模板类型, 但后来就开始呕吐了。我是否遗漏了他们隐式确定模板的技巧 参数,特别是在"C"实例上?如果只说"C"就好了。- 检查方法是否比下面的方法更容易?
以下是我针对这两种情况的示例代码:
#include <vector>
#include <type_traits>
#include <algorithm>
template<typename T, typename Alloc, template<typename _T=T, typename _Alloc=Alloc> class C >
concept PushBackMovable = std::is_same_v<decltype(std::declval<C<T,Alloc> >().push_back(std::move(T{}))),void> &&
std::is_same_v<decltype(std::declval<C<T,Alloc> >().push_back(T{})),void>;
template<std::movable T, typename Alloc, template<typename _T=T, typename _Alloc=Alloc> class C >
void operator+=( C<>& lhs, T rhs ) requires PushBackMovable<T, Alloc, C>
{
lhs.push_back( std::forward<T>( rhs ) );
}
int main() {
std::vector<int> ints;
int a = 5;
ints += 1;
ints += a;
std::copy(std::begin(ints), std::end(ints), std::ostream_iterator<int>(std::cout, " "));
}
感谢您的帮助。
解决方案
通过使用模板-模板参数,您已经将函数约束到遵循标准库模式的容器,但也约束到恰好有两个类型模板参数的类模板。这是一个很强的约束,在实践中通常毫无用处。也就是说,我建议您改为操作由类型模板参数表示的具体类型,并让概念验证您想要施加的任何要求。
此外,不要使用decltype
WITHstd::declval
WITHstd::is_same
来检查表达式的有效性。概念有专门的语法用于此目的,它只是将该表达式放在大括号中。
一个解决方案是将您要验证的内容合并到一个概念中,可能如下所示:
#include <concepts>
#include <utility>
#include <type_traits>
template <typename C, typename T>
concept PushBackMovable = requires (C c, T t) {
{ c.push_back(t) } -> std::same_as<void>;
{ c.push_back(std::move(t)) } -> std::same_as<void>;
};
template <typename T, PushBackMovable<std::remove_reference_t<T>> C>
void operator+=(C& lhs, T&& rhs)
{
lhs.push_back(std::forward<T>(rhs));
}
DEMO
相关文章