当相同的约束必须推导出不同类型时,为什么将概念放入类型说明符失败类型推导?

时间:2018-01-19 12:59:39

标签: 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>;

然后我们让编译器推导出所有数字:

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";

编译器推导出所有类型的参数类型:

auto foo<int, double, float, long double>(int, double, float, long double):

当我们尝试将约束分配到类型说明符中以编写更短的版本时:

auto foo2(Numeric arg1, Numeric arg2, Numeric arg3, Numeric arg4) {
    return 0.0 + arg1 + arg2 + arg3 + arg4;
}

虽然编译器令人惊讶地无法推断出这一点:

// err: deduction fails
//
// std::cout << foo2(1,2,3,4.0) << "\n"; 

似乎编译器尝试将所有类型推断为同一类型,这必须在此处失败。

为什么呢?编译器不应该能够从同一个约束中推断出不同的类型吗?

LIVE

1 个答案:

答案 0 :(得分:7)

这是概念TS中更具争议性的方面之一。当你说

#!/bin/bash
counter=1
while [ $counter -lt 999999 ]; do
    number=$(printf "%07d" "$counter")        
    let pre_counter=counter-1
    pre_numer=$(printf "%07d" "$pre_counter")  
    if [ ! -f ./$pre_numer.jpg ]; then
       sudo fswebcam -r 1920x1080 --no-banner ./$pre_numer.jpg
    else
        sudo fswebcam -r 1920x1080 --no-banner ./$number.jpg
        let counter=counter+1
    fi;
    sleep 30
done

这被翻译成好像你说过

template <typename T> concept bool C = true;

template <C T, C U>
void func(T t, U u);

但是,当您使用“缩写语法”来表示

template <typename T, typename U> requires (C<T> && C<U>)
void func(T t, U u);

这被翻译成好像你说过

void func(C t, C u); 

许多人认为这是违反直觉的,并且有proposal to change it。然而,其他人(包括Bjarne Stroustrup本人)赞成“持续演绎” - 请参阅Stroustrup的论文here

在撰写本文时,包含在C ++ 20草案中的Concepts TS的子集不包括缩写语法。目前尚不清楚它是否会在20年结束,如果是这样,它将使用什么样的推论 - 争论仍有待解决。