如何解决混用概念是一种改进还是不良做法?
看来您可以在概念中放入lambda,然后在其中编写代码。让我们以此为例。我更喜欢这些概念的标准概念,并且请记住,这仅出于本示例的目的-godbolt
template<class T>
concept labdified_concept =
requires {
[](){
T t,tt; // default constructible
T ttt{t}; // copy constructible
tt = t; //copy assignable
tt = std::move(t); // move assignable
};
};
代替:
template<class T>
concept normal_concept =
std::default_initializable<T> && std::movable<T> && std::copy_constructible<T>;
羊羔化是一种进步还是不良做法?从可读性角度来看。
解决方法
忽略这种机制中明显的可读性缺陷,实际上并没有奏效。请考虑以下内容:
template<labdified_concept T>
void foo(T t) {}
template<typename T>
void foo(T t) {}
概念规则告诉我们,如果给定的T
不满足labdified_concept
,则应实例化另一个foo
。但是,如果我们向这样的模板提供SS
,则不会发生这种情况。相反,由于labdified_concept<SS>
无法实例化,我们得到了一个硬错误。
requires
表达式中的内容具有特殊的处理方式,可以将某些类型的错误视为满足要求的失败。但是该处理不适用于lambda的主体。那里,格式错误的代码是格式错误的,因此在尝试实例化该代码时会遇到编译错误。
即使它起作用了,它仍然不起作用。概念具有复杂的概念包含规则,因此可以认为不同的概念比其他概念更加专业。这样就可以使用overloading on different concepts,它可以调用更受约束的概念。例如,仅需要default_initializable
的概念比需要default_initializable
和moveable
的概念更为通用。因此,如果一个类型同时满足这两种要求,则会采用后者,因为它受到的限制更大。
但这仅适用于concept
的特殊规则。在lambdas中隐藏要求将使其无法正常工作。
这无效。允许lambda进入未评估上下文的目的并不是突然允许SFINAE用于语句。
我们在[temp.deduct]/9中确实有明确的措辞:
出于模板自变量推导的目的,在函数类型或模板参数中出现的 lambda-表达式不被视为立即上下文的一部分。 [注意:目的是避免要求实现处理涉及任意语句的替换失败。 [示例:
template <class T> auto f(T) -> decltype([]() { T::invalid; } ()); void f(...); f(0); // error: invalid expression not part of the immediate context template <class T,std::size_t = sizeof([]() { T::invalid; })> void g(T); void g(...); g(0); // error: invalid expression not part of the immediate context template <class T> auto h(T) -> decltype([x = T::invalid]() { }); void h(...); h(0); // error: invalid expression not part of the immediate context template <class T> auto i(T) -> decltype([]() -> typename T::invalid { }); void i(...); i(0); // error: invalid expression not part of the immediate context template <class T> auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t)); // #1 void j(...); // #2 j(0); // deduction fails on #1,calls #2
— 结束示例] — 结束注释]
我们只是没有等同的要求。 gcc的行为确实符合您的期望:
template <typename T> concept C = requires { []{ T t; }; };
struct X { X(int); };
static_assert(!C<X>); // ill-formed
由于lambda的主体位于即时上下文之外,因此这不是替换失败,而是一个硬错误。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。