san*_*orn 4 c++ templates c++-concepts type-deduction
我们有:
template <typename ...T> concept bool Numerics = ( std::is_arithmetic_v<T> && ... ) ;
template <typename T> concept bool Numeric = std::is_arithmetic_v<T>;
Run Code Online (Sandbox Code Playgroud)
然后我们让编译器推导出所有数字:
template <typename T, typename U, typename V, typename W> requires Numerics<T,U,V,W>
auto foo(T arg1, U arg2, V arg3, W arg4) {
return 0.0 + arg1 + arg2 + arg3 + arg4;
}
std::cout << foo (1,2.0,3.0f,4.0l) << "\n";
Run Code Online (Sandbox Code Playgroud)
编译器推导出预期的所有参数类型:
auto foo<int, double, float, long double>(int, double, float, long double):
Run Code Online (Sandbox Code Playgroud)
当我们尝试将约束分配到类型说明符中以编写更短的版本时:
auto foo2(Numeric arg1, Numeric arg2, Numeric arg3, Numeric arg4) {
return 0.0 + arg1 + arg2 + arg3 + arg4;
}
Run Code Online (Sandbox Code Playgroud)
虽然,编译器令人惊讶地无法推断出这一点:
// err: deduction fails
//
// std::cout << foo2(1,2,3,4.0) << "\n";
Run Code Online (Sandbox Code Playgroud)
似乎编译器尝试将所有类型推断为相同类型,这必须在此处失败.
为什么?编译器是否应该能够从相同的约束中推断出不同的类型?
这是概念TS中更具争议性的方面之一.当你说
template <typename T> concept bool C = true;
template <C T, C U>
void func(T t, U u);
Run Code Online (Sandbox Code Playgroud)
这被翻译成好像你说的那样
template <typename T, typename U> requires (C<T> && C<U>)
void func(T t, U u);
Run Code Online (Sandbox Code Playgroud)
但是,当您使用"缩写语法"来表示时
void func(C t, C u);
Run Code Online (Sandbox Code Playgroud)
这被翻译成好像你说的那样
template <typename T> requires C<T>
void func(T t, T u);
Run Code Online (Sandbox Code Playgroud)
许多人认为这是违反直觉的,并且有人建议改变它.然而,其他人(包括了Bjarne Stroustrup的自己)都赞成"一贯演绎"的-见Stroustrup的纸在这里.
在撰写本文时,包含在C++ 20草案中的概念TS的子集不包括缩写语法.目前尚不清楚它是否会在20年结束,如果是这样,它将使用什么样的推论 - 争论仍有待解决.