Reputation: 4840
Consider this code:
constexpr int XX = 10;
template < auto& II > struct Ban { };
template < auto& II >
std:: true_type test(Ban<II>*);
std::false_type test(...);
and:
using BB = decltype(test(std::declval<Ban<XX>*>()));
Here I am expecting BB
to be std::true_type
, but it is std::false_type
for both gcc-8.3
and clang-8.0
. Is this a bug in these compilers?
Note that BB
becomes std::true_type
when I change auto&
to auto
. Also note that for gcc
situation is the same if I use int const
instead of auto
, so int const&
yields to std::false_type
, while int const
yields to std::true_type
, while for clang
int const&
yields to std::true_type
. You can find live example here.
Is there a workaround to do this kind of SFINAE with a template of non-type reference? The point is to have a utility like IsInstantiationOfBan
.
Upvotes: 1
Views: 82
Reputation: 13988
Maybe instead of auto &
you want decltype(auto)
:
#include <type_traits>
constexpr int XX = 10;
template <decltype(auto) II > struct Ban { };
template <decltype(auto) II >
std::true_type test(Ban<II>*);
std::false_type test(...);
int main()
{
using BB = decltype(test(std::declval<Ban<(XX)>*>()));
// ^ ^ be careful for brackets!
static_assert(std::is_same_v<BB, std::true_type>);
return 0;
}
In case of your first question, clang probably requires the const
specifier before auto &
to fulfil const correctness (constexpr variable is also presumably const
). [example].
Upvotes: 2