qwe*_*qwe 5 c++ gcc c++-concepts
在编译以下(减少的)代码时:
#include <tuple>
#include <stdlib.h>
template<size_t N> struct tying;
template<> struct tying<1> {static auto function(auto& o) -> decltype(auto) {auto& [p1] = o;return std::tie(p1);}};
template<> struct tying<2> {static auto function(auto& o) -> decltype(auto) {auto& [p1,p2] = o;return std::tie(p1,p2);}};
template<typename T, size_t N> concept bool n_components =
requires(T& object) {
{ tying<N>::function(object) };
};
typedef struct
{
int a;
float b;
} test_t;
int main(int argc, char* argv[])
{
constexpr size_t n = 1;
constexpr bool t = n_components<test_t, n>;
printf("n_components<test_t, %d>: %s\n", n, t ? "yes" : "nope");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用 gcc 特定选项时-std=c++1z -fconcepts,gcc(7.3.0 版,以及 Godbolt 的 x86-64 gcc-trunk)失败并出现错误:
错误:仅为结构化绑定提供了 1 个名称
注意:而“test_t”分解为 2 个元素
我对此感到非常惊讶,因为错误requires-expression在n_components.
注意:用constexpr size_t n = 1;其他值替换“修复”错误,所以我认为n_components约束不是罪魁祸首:
n = 2的n_components约束评估为“真”的预期。n = 3的n_components,由于指非专业化-约束评估为预期的“伪”tying<3>结构。似乎没有其他编译器支持 C++ 概念和可用的结构化绑定。
附注。我在玩“穷人的反思”又名,magic_get并希望is_braces_constructible用更强大的东西代替不可靠的特征......
我对此感到非常惊讶,因为错误在需求表达式中“引发”
准确地说,错误发生在function你写的 s 的正文中。我们可以将您的代码归结为:
void function(auto& arg);
void function_with_body(auto& arg)
{
arg.inexistent_member;
}
template<typename Arg>
concept bool test = requires(Arg arg) { function(arg); };
// never fires
static_assert( test<int> );
template<typename Arg>
concept bool test_with_body = requires(Arg arg) { function_with_body(arg); };
// never fires
static_assert( test_with_body<int> );
Run Code Online (Sandbox Code Playgroud)
(在Coliru)
就表达式而言requires,函数调用是有效的 C++ 表达式:它们的返回和参数类型没有什么棘手的,并且提供的参数可以很好地传递。不对函数体执行任何检查,并且有充分的理由:函数或函数模板可能已声明但尚未定义(即,如 的情况function)。相反,通常由函数模板编写者来确保函数体对于所有(合理的)专业化都没有错误。
您的代码使用返回类型推导,但这不会产生太大的差异:您也可以使用占位符类型(例如decltype(auto))声明一个函数,而无需定义它。(虽然对这样一个函数的调用实际上是requires一个无效的表达式,因为类型无法被推导并且对于表达式来说是可见的,但这不是你正在做的。)用前概念的说法,返回类型推导不是 SFINAE-友好的。
至于围绕结构化绑定编写约束的更广泛问题,您运气不好。据我所知,这些都是所有的障碍:
std::tuple_size仅适用于类似元组的类型。)。不过,这可以通过盲目地按递增顺序尝试尺寸来解决。requires。您可以做的最接近的事情是模拟该语言在实际结构化绑定期间所做的事情。这可以让您支持类似元组的类型(包括数组),但不支持“哑”聚合。
(range-for是语句级约束的另一种情况,您无法将其放入表达式约束中,并且模拟该语言只能让您到目前为止。)