Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does putting concept to type specifier fail type deduction when the same constraint must deduce different types?

We have:

template <typename ...T> concept bool Numerics = ( std::is_arithmetic_v<T> && ... ) ;
template <typename T>    concept bool Numeric  =   std::is_arithmetic_v<T>;

Then we let compiler deduce all the numbers:

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

Compiler deduces all argument types like expected:

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

When we try distribute constraints into type specifier for writing a shorter version:

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

Though, compiler surprisingly fails to deduce this:

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

It seems compiler try deduce all into the same type, which must fails here.

Why? Shouldn't compiler be able to deduce different types from the same contraint?

LIVE

like image 486
sandthorn Avatar asked Mar 07 '23 03:03

sandthorn


1 Answers

This is one of the more controversial aspects of the Concepts TS. When you say

template <typename T> concept bool C = true;

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

this is translated as if you had said

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

However, when you use the "abbreviated syntax" to say

void func(C t, C u); 

this is translated as if you had said

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

Many people consider this to be counterintuitive, and there has been a proposal to change it. However, others (including Bjarne Stroustrup himself) are in favour of "consistent deduction" -- see Stroustrup's paper here.

At the time of writing, the subset of the Concepts TS incorporated into the C++20 draft does not include the abbreviated syntax. It's not clear at the moment whether it will end up in '20, and if so, what sort of deduction it will use -- the arguments are still to be resolved.

like image 159
Tristan Brindle Avatar answered Mar 09 '23 16:03

Tristan Brindle