Consider the following concept:
template< typename T, std::size_t Value >
concept Is_ = requires(T&&)
{
requires Value == std::remove_cvref_t< T >::value;
};
Associated with the function overloads:
template< Is_< 2 > T >
void foo(T&&)
{
std::cout << "Value is 2!" << std::endl;
}
template< typename T >
void foo(T&&)
{
std::cout << "Either no value or it isn't 2!" << std::endl;
}
Finally, let's play with the above functions:
foo(std::integral_constant< std::size_t, 2 >{}); // Choose the constrained overload
foo(std::tuple{}) // Choose the generic impl
Now if I define the following helper variable template:
template< typename T >
inline constexpr auto t_value = T::value;
And use it in the concept for brevity's sake:
template< typename T, std::size_t Value >
concept Is_ = requires(T&&)
{
requires Value == t_value< std::remove_cvref_t< T > >;
};
I now get this compiler error:
main.cpp: In instantiation of 'constexpr const auto t_value':
main.cpp:11:23: required by substitution of 'template requires Is_<T, 2> void foo(T&&) [with T = int]'
main.cpp:27:8: required from here
main.cpp:6:29: error: 'value' is not a member of 'int'
6 | constexpr auto t_value = T::value;
Having invalid type aliases is however perfectly fine.
MVCE is available here: https://coliru.stacked-crooked.com/a/653bb52448ca1db3
Where does this behavior come from?