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))
.