Dim*_*hev 3 c++ c++-concepts c++20
看来您可以将 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
};
};
Run Code Online (Sandbox Code Playgroud)
代替:
template<class T>
concept normal_concept =
std::default_initializable<T> && std::movable<T> && std::copy_constructible<T>;
Run Code Online (Sandbox Code Playgroud)
羔羊化是一种改进还是不好的做法?从可读性的角度来看也是如此。
忽略这种机制中明显的可读性缺陷,它实际上不起作用。考虑以下:
template<labdified_concept T>
void foo(T t) {}
template<typename T>
void foo(T t) {}
Run Code Online (Sandbox Code Playgroud)
概念规则告诉我们,如果一个给定的T不满足labdified_concept,那么另一个foo应该被实例化。但是,如果我们提供SS这样的模板,则不会发生这种情况。相反,我们得到了一个硬错误,因为labdified_concept<SS>无法实例化。
一个内部的东西requires表达了特殊的处理,使某些类型的错误应被视为失败,以满足需求。但是这种处理不适用于 lambda 的主体。在那里,病态的代码是形成不良的,因此你试图实例它的时候得到一个编译错误。
即使它确实有效,它仍然不起作用。概念具有包含概念的复杂规则,这使得不同的概念被认为比其他概念更高度专业化。这允许重载不同的概念,从而可以调用更受约束的概念。例如,一个仅需要的概念default_initializable比需要default_initializable和的概念更通用moveable。因此,如果一个类型同时满足这两个条件,则将采用后者,因为它受到更多约束。
但这仅适用于concepts的特殊规则。在 lambdas 中隐藏需求不允许这样做。
这应该是无效的。在未评估的上下文中允许 lambda 表达式的重点不是突然允许 SFINAE 用于语句。
我们在[temp.deduct]/9中确实有一些措辞明确说明了这一点:
甲λ-表达出现在函数式或模板参数不被认为对模板参数推导的目的,即时上下文的一部分。[注意:目的是避免要求实现处理涉及任意语句的替换失败。[示例:
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)
因为 lambda 的主体在直接上下文之外,所以它不是替换失败,而是一个硬错误。
| 归档时间: |
|
| 查看次数: |
139 次 |
| 最近记录: |