Home > Software design >  concepts return type requirement syntax two versus one template parm
concepts return type requirement syntax two versus one template parm

Time:12-03

I am wondering how the std::same_as is defined and how we use it in a concept or requirement.

Example:

void f1() { } 
bool f2() { return true; }

template < typename T>
void Do( T func )
{
    if constexpr ( requires { { func() } -> std::same_as<bool>; } ) 
    {   
        std::cout << "Func returns bool " << std::endl;
    }   

    if constexpr ( requires { { func() } -> std::same_as<void>; } ) 
    {   
        std::cout << "Func returns void " << std::endl;
    }   
}

int main()
{
    Do( f1 );
    Do( f2 );
}

That works as expected.

But if I look on the definition of std::same_as I find a possible implementation:

namespace detail {
    template< class T, class U >
    concept SameHelper = std::is_same_v<T, U>;
}
 
template< class T, class U >
concept same_as = detail::SameHelper<T, U> && detail::SameHelper<U, T>;

And what makes me wonder is that I see two template parms T and U in that case while we only need to write one like { { func() } -> std::same_as<bool>; }.

Is it some kind of magic that a { { func() } -> std::same_as<bool>; } will be converted to std::same_as<magic_return_type, bool> in that case?

CodePudding user response:

A concept is generally similar to a constexpr inline bool variable template. However, it does have special properties. With regard to this question, a concept whose first template parameter is a type is a special kind of concept: a "type concept".

In certain locations, a type concept can be used without its first template parameter. In those places, the first parameter will be deduced based on how it gets used.

In compound requirements of a requires expression, a type concept is what follows the ->. The first parameter of the concept will be filled in by the type of the expression E in the {}, as if by decltype((E)).

  • Related